@cratis/pi 2.22.0 → 2.23.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.
Files changed (111) hide show
  1. package/package/corpus/agents/backend-developer.md +6 -5
  2. package/package/corpus/agents/code-reviewer.md +7 -7
  3. package/package/corpus/agents/coordinator.md +5 -4
  4. package/package/corpus/agents/frontend-developer.md +34 -40
  5. package/package/corpus/agents/orchestrator.md +5 -4
  6. package/package/corpus/agents/performance-reviewer.md +5 -4
  7. package/package/corpus/agents/planner.md +5 -4
  8. package/package/corpus/agents/repository-investigation-reviewer.md +2 -1
  9. package/package/corpus/agents/repository-investigator.md +2 -1
  10. package/package/corpus/agents/security-reviewer.md +5 -4
  11. package/package/corpus/agents/slice-implementer.md +8 -2
  12. package/package/corpus/agents/spec-writer.md +6 -4
  13. package/package/corpus/harnesses/pi/extensions/cratis-rules/index.ts +233 -10
  14. package/package/corpus/harnesses/pi/extensions/subagent/agents.ts +52 -7
  15. package/package/corpus/harnesses/pi/extensions/subagent/index.ts +14 -0
  16. package/package/corpus/hooks/README.md +29 -27
  17. package/package/corpus/hooks/agent-stop.md +1 -5
  18. package/package/corpus/hooks/scripts/cratis-patterns.json +1 -1
  19. package/package/corpus/hooks/scripts/validate-package-subpaths.sh +1 -2
  20. package/package/corpus/prompts/ship-changes.prompt.md +4 -0
  21. package/package/corpus/prompts/verify-ai-setup.prompt.md +17 -7
  22. package/package/corpus/rules/ai-distribution.md +60 -0
  23. package/package/corpus/rules/application-profile.md +73 -0
  24. package/package/corpus/rules/components.md +77 -44
  25. package/package/corpus/rules/dialogs.md +24 -20
  26. package/package/corpus/rules/efcore.md +35 -187
  27. package/package/corpus/rules/framework.md +1 -1
  28. package/package/corpus/rules/frontend-quality.md +1 -1
  29. package/package/corpus/rules/frontend-testing.md +4 -4
  30. package/package/corpus/rules/general.md +21 -162
  31. package/package/corpus/rules/guards-and-fuses.md +24 -10
  32. package/package/corpus/rules/local-work-artifacts.md +6 -0
  33. package/package/corpus/rules/new-repository-intake.md +34 -0
  34. package/package/corpus/rules/orleans.md +13 -27
  35. package/package/corpus/rules/profiles.md +6 -0
  36. package/package/corpus/rules/react.md +12 -12
  37. package/package/corpus/rules/reactors.md +28 -5
  38. package/package/corpus/rules/rtk.md +13 -3
  39. package/package/corpus/rules/specs.scenarios.csharp.md +18 -3
  40. package/package/corpus/rules/specs.typescript.md +1 -1
  41. package/package/corpus/rules/storybook.md +2 -2
  42. package/package/corpus/rules/typescript.md +1 -0
  43. package/package/corpus/rules/verification-discipline.md +7 -1
  44. package/package/corpus/rules/vertical-slices.md +20 -15
  45. package/package/corpus/rules/writing-correct-examples.md +1 -0
  46. package/package/corpus/skills/cratis-application-react-specifications/SKILL.md +4 -4
  47. package/package/corpus/skills/cratis-application-slice-specifications/SKILL.md +16 -8
  48. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/SKILL.md +6 -4
  49. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authentication.md +1 -1
  50. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authorization.md +1 -1
  51. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/frontend.md +1 -1
  52. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/local-development.md +1 -1
  53. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/tenancy.md +7 -4
  54. package/package/corpus/skills/cratis-arc-command/SKILL.md +9 -7
  55. package/package/corpus/skills/cratis-arc-command/references/command-result.md +1 -1
  56. package/package/corpus/skills/cratis-arc-command/references/handler-shapes.md +2 -2
  57. package/package/corpus/skills/cratis-arc-command/references/proxy-generation.md +6 -3
  58. package/package/corpus/skills/cratis-arc-command/references/read-model-injection.md +1 -1
  59. package/package/corpus/skills/cratis-arc-command-execution/SKILL.md +12 -2
  60. package/package/corpus/skills/cratis-arc-command-validation/SKILL.md +5 -3
  61. package/package/corpus/skills/cratis-arc-ef-core-migration/SKILL.md +7 -4
  62. package/package/corpus/skills/cratis-arc-observable-query-http/SKILL.md +10 -3
  63. package/package/corpus/skills/cratis-arc-query-paging/SKILL.md +13 -8
  64. package/package/corpus/skills/cratis-arc-react-page/SKILL.md +27 -24
  65. package/package/corpus/skills/cratis-arc-react-page/references/data-page.md +15 -11
  66. package/package/corpus/skills/cratis-arc-react-page/references/data-tables.md +9 -2
  67. package/package/corpus/skills/cratis-arc-react-page/references/dialogs.md +11 -9
  68. package/package/corpus/skills/cratis-arc-react-page/references/queries-and-commands.md +26 -2
  69. package/package/corpus/skills/cratis-chronicle-cli-operations/SKILL.md +19 -13
  70. package/package/corpus/skills/cratis-chronicle-client-dotnet/SKILL.md +17 -15
  71. package/package/corpus/skills/cratis-chronicle-client-elixir/SKILL.md +24 -20
  72. package/package/corpus/skills/cratis-chronicle-client-kotlin/SKILL.md +26 -15
  73. package/package/corpus/skills/cratis-chronicle-client-typescript/SKILL.md +15 -11
  74. package/package/corpus/skills/cratis-chronicle-compliance/SKILL.md +14 -3
  75. package/package/corpus/skills/cratis-chronicle-event-constraints/SKILL.md +13 -6
  76. package/package/corpus/skills/cratis-chronicle-event-modeling/SKILL.md +2 -2
  77. package/package/corpus/skills/cratis-chronicle-event-specifications/SKILL.md +11 -5
  78. package/package/corpus/skills/cratis-chronicle-event-type-migration/SKILL.md +2 -2
  79. package/package/corpus/skills/cratis-chronicle-multi-tenancy/SKILL.md +2 -2
  80. package/package/corpus/skills/cratis-chronicle-projection/SKILL.md +23 -4
  81. package/package/corpus/skills/cratis-chronicle-projection/references/fluent-builder.md +1 -1
  82. package/package/corpus/skills/cratis-chronicle-projection/references/model-bound-attributes.md +2 -2
  83. package/package/corpus/skills/cratis-chronicle-reactor/SKILL.md +22 -8
  84. package/package/corpus/skills/cratis-chronicle-read-model/SKILL.md +1 -1
  85. package/package/corpus/skills/cratis-chronicle-read-model/references/queries.md +1 -1
  86. package/package/corpus/skills/cratis-chronicle-read-model-specifications/SKILL.md +3 -1
  87. package/package/corpus/skills/cratis-chronicle-reducer/SKILL.md +1 -1
  88. package/package/corpus/skills/cratis-chronicle-web-workbench/SKILL.md +19 -11
  89. package/package/corpus/skills/cratis-cli-terminal-workbench/SKILL.md +11 -6
  90. package/package/corpus/skills/cratis-code-review/SKILL.md +8 -6
  91. package/package/corpus/skills/cratis-components-accessibility/SKILL.md +112 -82
  92. package/package/corpus/skills/cratis-components-schema-editor/SKILL.md +12 -10
  93. package/package/corpus/skills/cratis-components-stepper-command-dialog/SKILL.md +11 -12
  94. package/package/corpus/skills/cratis-components-styling/SKILL.md +204 -170
  95. package/package/corpus/skills/cratis-components-toolbar/SKILL.md +32 -26
  96. package/package/corpus/skills/cratis-event-model-diagram/SKILL.md +1 -1
  97. package/package/corpus/skills/cratis-fundamentals-concept/SKILL.md +2 -2
  98. package/package/corpus/skills/cratis-fundamentals-type-discovery/SKILL.md +2 -2
  99. package/package/corpus/skills/cratis-lens-browser-extension/SKILL.md +4 -2
  100. package/package/corpus/skills/cratis-performance-review/SKILL.md +4 -2
  101. package/package/corpus/skills/cratis-screenplay-model-authoring/SKILL.md +15 -5
  102. package/package/corpus/skills/cratis-security-review/SKILL.md +20 -3
  103. package/package/corpus/skills/cratis-specifications-csharp/SKILL.md +3 -3
  104. package/package/corpus/skills/cratis-specifications-csharp/references/application-scenarios.md +12 -8
  105. package/package/corpus/skills/cratis-specifications-csharp/references/csharp-patterns.md +1 -1
  106. package/package/corpus/skills/cratis-specifications-csharp/references/integration-specs.md +7 -3
  107. package/package/corpus/skills/cratis-specifications-typescript/SKILL.md +6 -3
  108. package/package/corpus/skills/cratis-specifications-typescript/references/typescript-patterns.md +21 -4
  109. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +29 -17
  110. package/package.json +1 -1
  111. package/package/corpus/rules/terminal-commands.md +0 -19
@@ -15,8 +15,10 @@ dispatch.
15
15
 
16
16
  | Package | Version | Purpose |
17
17
  | --- | --- | --- |
18
- | `Cratis.Arc.Core` | `22.10.4` | `Cratis.Arc.Commands.ICommandPipeline`, `CommandResult`, `ValidationResultSeverity` |
19
- | `Cratis.Arc.Chronicle` | `22.10.4` | analyzer `ARCCHR0006` for reactor replay |
18
+ | `Cratis.Arc.Core` | `22.16.0` | `Cratis.Arc.Commands.ICommandPipeline`, `CommandResult`, `ValidationResultSeverity` |
19
+ | `Cratis.Arc.Chronicle` | `22.16.0` | analyzer `ARCCHR0006` for reactor replay |
20
+
21
+ > Re-verified at the versions above by **symbol and signature**: every type, attribute and member this skill names exists at that tag, and the public surface it describes is unchanged since the previous verification (Chronicle 16.45.x / Arc 22.10.4 — the Chronicle 16→18 client diff is converters, options and doc comments; no type was removed or renamed). Behavior claims were verified at the earlier tag unless a section says otherwise.
20
22
 
21
23
  Reverify before claiming support for another version.
22
24
 
@@ -29,6 +31,14 @@ inject `IEventLog` (`ARCCHR0007`).
29
31
 
30
32
  ## Inject and execute
31
33
 
34
+ > **Reactors have a declarative alternative.** With the Arc Chronicle integration a
35
+ > reactor handler can **return** the `[Command]` (or a collection of commands) and
36
+ > Arc executes it; a denied or invalid result fails the partition instead of being
37
+ > discarded, and `[ExecuteCommandsAsSystem]` on the reactor class supplies a
38
+ > principal for those returned commands. That attribute does **not** cover manual
39
+ > `Execute` calls — the form below needs its own execution context. See the
40
+ > **cratis-chronicle-reactor** skill.
41
+
32
42
  ```csharp
33
43
  public class <Name>Reactor(ICommandPipeline pipeline) : IReactor
34
44
  {
@@ -23,11 +23,13 @@ rejection on it.)
23
23
 
24
24
  | Package | Version | Purpose |
25
25
  | --- | --- | --- |
26
- | `Cratis.Arc.Core` | `22.10.4` | `CommandValidator<T>`, `ConceptValidator<T>`, `ValidationResult`, `CommandResult`, the command pipeline, `ARC0004`–`ARC0013` |
27
- | `Cratis.Fundamentals` | `7.18.2` | `Cratis.Monads.Result<TResult, TError>` |
28
- | `Cratis.Chronicle` | `16.45.2` | Read-model resolution for command-side injection |
26
+ | `Cratis.Arc.Core` | `22.16.0` | `CommandValidator<T>`, `ConceptValidator<T>`, `ValidationResult`, `CommandResult`, the command pipeline, `ARC0004`–`ARC0013` |
27
+ | `Cratis.Fundamentals` | `7.19.2` | `Cratis.Monads.Result<TResult, TError>` |
28
+ | `Cratis.Chronicle` | `18.3.0` | Read-model resolution for command-side injection |
29
29
  | `FluentValidation` | `12.1.1` | `RuleFor(...)`, `.WithMessage(...)` |
30
30
 
31
+ > Re-verified at the versions above by **symbol and signature**: every type, attribute and member this skill names exists at that tag, and the public surface it describes is unchanged since the previous verification (Chronicle 16.45.x / Arc 22.10.4 — the Chronicle 16→18 client diff is converters, options and doc comments; no type was removed or renamed). Behavior claims were verified at the earlier tag unless a section says otherwise.
32
+
31
33
  Reverify against the owning product repository before claiming support for
32
34
  another version.
33
35
 
@@ -15,10 +15,12 @@ Everything else is ordinary EF Core.
15
15
 
16
16
  | Package | Version | Purpose |
17
17
  | --- | --- | --- |
18
- | `Cratis.Arc.EntityFrameworkCore` | `22.10.4` | `BaseDbContext`, `ReadOnlyDbContext`, `WithEntityFrameworkCore`, column helpers, `EntityFrameworkReadModelForCommandResolver` |
19
- | `Cratis.Arc.Core` | `22.10.4` | `Cratis.Arc.Queries.ModelBound.ReadModelAttribute`, `ICanResolveReadModelForCommand` |
18
+ | `Cratis.Arc.EntityFrameworkCore` | `22.16.0` | `BaseDbContext`, `ReadOnlyDbContext`, `WithEntityFrameworkCore`, column helpers, `EntityFrameworkReadModelForCommandResolver` |
19
+ | `Cratis.Arc.Core` | `22.16.0` | `Cratis.Arc.Queries.ModelBound.ReadModelAttribute`, `ICanResolveReadModelForCommand` |
20
20
  | `Microsoft.EntityFrameworkCore` | `10.0.11` | EF Core itself, including all migration tooling |
21
21
 
22
+ > Re-verified at the versions above by **symbol and signature**: every type, attribute and member this skill names exists at that tag, and the public surface it describes is unchanged since the previous verification (Chronicle 16.45.x / Arc 22.10.4 — the Chronicle 16→18 client diff is converters, options and doc comments; no type was removed or renamed). Behavior claims were verified at the earlier tag unless a section says otherwise.
23
+
22
24
  Reverify before claiming support for another version.
23
25
 
24
26
  ⚠️ **Arc ships no migration tooling of its own.** There is no design-time
@@ -148,8 +150,9 @@ migrationBuilder.CreateTable(
148
150
  `StringColumn`, `NumberColumn<T>`, `BoolColumn`, `AutoIncrementColumn`,
149
151
  `GuidColumn` and `DateTimeOffsetColumn` all take the `MigrationBuilder` as their
150
152
  first argument — that is how they learn which database they are generating for.
151
- All of them default `nullable` to **`true`**, so a required column has to say
152
- `nullable: false` explicitly.
153
+ All of them except `AutoIncrementColumn` default `nullable` to **`true`**, so a
154
+ required column has to say `nullable: false` explicitly; `AutoIncrementColumn`
155
+ has no `nullable` parameter and is always `NOT NULL`.
153
156
 
154
157
  On `MigrationBuilder`, for an existing table:
155
158
 
@@ -13,7 +13,9 @@ request is made. Choose the transport first, then the command.
13
13
 
14
14
  | Package | Version | Purpose |
15
15
  | --- | --- | --- |
16
- | `Cratis.Arc.Core` | `22.10.4` | `ObservableQueryHttp`, `ObservableQueryHandler`, the demultiplexer routes |
16
+ | `Cratis.Arc.Core` | `22.16.0` | `ObservableQueryHttp`, `ObservableQueryHandler`, the demultiplexer routes |
17
+
18
+ > Re-verified at the versions above by **symbol and signature**: every type, attribute and member this skill names exists at that tag, and the public surface it describes is unchanged since the previous verification (Chronicle 16.45.x / Arc 22.10.4 — the Chronicle 16→18 client diff is converters, options and doc comments; no type was removed or renamed). Behavior claims were verified at the earlier tag unless a section says otherwise.
17
19
 
18
20
  Reverify before claiming support for another version. This skill is read-only
19
21
  inspection of an endpoint the user already has; it neither implements the query
@@ -29,7 +31,12 @@ handler decides in this order:
29
31
  (case-insensitive);
30
32
  3. **plain HTTP** — everything else, answered once and closed.
31
33
 
32
- A plain `curl` sends neither, so it always lands on the third case.
34
+ A plain `curl` sends neither, so it always lands on the third case — and there
35
+ the two result shapes part ways: an **`ISubject<T>`** query answers with one
36
+ `QueryResult` as described below, while an **`IAsyncEnumerable<T>`** query
37
+ answers **HTTP 400** with `{ "message": "AsyncEnumerable queries require WebSocket connection" }`
38
+ and never a `QueryResult`. Everything that follows on this page is about
39
+ `ISubject<T>`; inspect an `IAsyncEnumerable<T>` query over WebSocket.
33
40
 
34
41
  ## Snapshot: the current value, once
35
42
 
@@ -37,7 +44,7 @@ A plain `curl` sends neither, so it always lands on the third case.
37
44
  curl "https://<host>/<api-prefix>/<route>"
38
45
  ```
39
46
 
40
- The response is one JSON `QueryResult`.
47
+ The response is one JSON `QueryResult` (for an `ISubject<T>` query — see above).
41
48
 
42
49
  ⚠️ **When the observable has not produced its first value yet, this returns HTTP
43
50
  202 Accepted with a not-ready result** — no exception, no data. That is a normal
@@ -13,10 +13,12 @@ the query string — you choose a **return shape** that the framework can narrow
13
13
 
14
14
  | Package | Version | Purpose |
15
15
  | --- | --- | --- |
16
- | `Cratis.Arc.Core` | `22.10.4` | `QueryableQueryRenderer`, `Paging`, `Sorting`, `PagingInfo` |
17
- | `Cratis.Arc.MongoDB` | `22.10.4` | `Observe` helpers that page at the source |
18
- | `Cratis.Arc.EntityFrameworkCore` | `22.10.4` | `DbSet<T>` observe helpers that page at the source |
19
- | `@cratis/arc.react` | `22.10.4` | `useWithPaging`, `useSuspenseWithPaging` |
16
+ | `Cratis.Arc.Core` | `22.16.0` | `QueryableQueryRenderer`, `Paging`, `Sorting`, `PagingInfo` |
17
+ | `Cratis.Arc.MongoDB` | `22.16.0` | `Observe` helpers that page at the source |
18
+ | `Cratis.Arc.EntityFrameworkCore` | `22.16.0` | `DbSet<T>` observe helpers that page at the source |
19
+ | `@cratis/arc.react` | `22.16.0` | `useWithPaging`, `useSuspenseWithPaging` |
20
+
21
+ > Re-verified at the versions above by **symbol and signature**: every type, attribute and member this skill names exists at that tag, and the public surface it describes is unchanged since the previous verification (Chronicle 16.45.x / Arc 22.10.4 — the Chronicle 16→18 client diff is converters, options and doc comments; no type was removed or renamed). Behavior claims were verified at the earlier tag unless a section says otherwise.
20
22
 
21
23
  Reverify before claiming support for another version. A small, bounded result
22
24
  set does not need any of this — `IEnumerable<T>` is fine.
@@ -25,7 +27,7 @@ set does not need any of this — `IEnumerable<T>` is fine.
25
27
 
26
28
  | Query-string key | Effect |
27
29
  | --- | --- |
28
- | `pageSize` | **Required to page at all.** Must be greater than 0 |
30
+ | `pageSize` | **Required to page at all** on the query string; any parseable integer is accepted (`0` yields an empty page, negatives are clamped by `Skip`) — the JSON body reader, by contrast, treats `pageSize <= 0` as not paged |
29
31
  | `page` | Zero-based. Defaults to `0` when `pageSize` is present |
30
32
  | `sortby` | Field name; PascalCased before use, so `?sortby=name` sorts on `Name` |
31
33
  | `sortDirection` | `desc` (case-insensitive) sorts descending; **anything else, including a missing value, is ascending** |
@@ -36,9 +38,12 @@ Two consequences that surprise people:
36
38
  - **Sorting needs both keys.** `sortby` without `sortDirection` is ignored
37
39
  entirely.
38
40
 
39
- Paging is validated before the query runs: `page` must be `>= 0` and `pageSize`
40
- must be `> 0`, and a violation comes back as a validation failure rather than a
41
- crash.
41
+ Paging is **not** validated on the request path at 22.16.0: `PageNumber`/`PageSize`
42
+ concept validators exist (`page >= 0`, `pageSize > 0`) but nothing feeds the
43
+ query-string paging into them, so an out-of-range value produces an empty or
44
+ clamped page rather than a validation failure. Validate paging arguments in the
45
+ frontend, or expose them as explicit query arguments if the rule must be
46
+ enforced.
42
47
 
43
48
  ## Which return shapes page
44
49
 
@@ -15,21 +15,20 @@ This skill is verified against these exact package contracts:
15
15
 
16
16
  | Package | Version | Verified from |
17
17
  | --- | --- | --- |
18
- | `@cratis/components` | `3.0.0` | its package manifest and component sources |
19
- | `@cratis/arc` | `>=20.3.1 <23` | peer range declared by `@cratis/components@3.0.0` |
20
- | `@cratis/arc.react` | `>=20.3.1 <23` | peer range declared by `@cratis/components@3.0.0` |
21
- | `primereact` | `^11.0.0` | peer of `@cratis/components@3.0.0` |
22
- | `primeicons` | `^8.0.0` | peer of `@cratis/components@3.0.0` |
23
- | `react` | `^19.0.0` | peer of `@cratis/components@3.0.0` |
18
+ | `@cratis/components` | `4.6.0` | its package manifest (`exports`, peers), `Source/DataPage/*`, `Source/DataTables/*`, `Source/Dialogs/*`, `Source/CommandDialog/*`, `Source/MIGRATION.md` |
19
+ | `@cratis/arc` | `>=20.3.1 <23` | peer range declared by `@cratis/components@4.6.0` |
20
+ | `@cratis/arc.react` | `>=20.3.1 <23` | peer range declared by `@cratis/components@4.6.0` |
21
+ | `react` | `^19.0.0` | peer of `@cratis/components@4.6.0` |
24
22
 
25
23
  `@cratis/arc.react.mvvm` ships with `@cratis/arc.react` and is an explicit
26
24
  application dependency. Reverify before claiming another version.
27
25
 
28
26
  ## Import from subpaths, never the root barrel
29
27
 
30
- The root `@cratis/components` entry exports **namespaces**, not components —
31
- `import { DataPage } from '@cratis/components'` yields a namespace object whose
32
- component is `DataPage.DataPage`. Always import from the subpath:
28
+ The root `@cratis/components` entry is **setup-only** — `CratisComponentsProvider`
29
+ and its configuration types. `import { DataPage } from '@cratis/components'` is a
30
+ compile error; the Components 3 root namespaces are gone. Always import from the
31
+ subpath:
33
32
 
34
33
  ```tsx
35
34
  import { DataPage, MenuItem, Column } from '@cratis/components/DataPage';
@@ -45,18 +44,21 @@ import { DialogProps, DialogResult, useDialog } from '@cratis/arc.react/dialogs'
45
44
  regenerated the TypeScript proxies. Generated proxies carry a
46
45
  `**DO NOT EDIT** - This file is an automatically generated file.` header —
47
46
  fix the C# source and rebuild instead of editing one.
48
- - The app must mount `CratisComponentsProvider` (from
49
- `@cratis/components/Common`) above every Cratis component. PrimeReact 11
50
- resolves its configuration from a provider, so components fail without one.
51
- - The app must import the stylesheets explicitly; components no longer import
47
+ - The app must mount `CratisComponentsProvider` (from the package root,
48
+ `@cratis/components`) above every Cratis component — it carries the locale,
49
+ the Components-owned labels and the toast region (`toaster`).
50
+ - The app must import the stylesheets explicitly; components do not import
52
51
  their own CSS:
53
52
 
54
53
  ```ts
55
- import '@cratis/components/tokens'; // the --cratis-* token layer
56
- import '@cratis/components/styles'; // every component stylesheet
57
- import '@cratis/components/theme'; // optional license-free baseline look
54
+ import '@cratis/components/tokens'; // the --cratis-* token seam
55
+ import '@cratis/components/styles'; // structural rules for every component
56
+ import '@cratis/components/theme'; // optional: the maintained baseline look
58
57
  ```
59
58
 
59
+ Components has no vendor UI dependency — do not install PrimeReact or an icon
60
+ font for it. Menu icons are React component types (`react-icons` works).
61
+
60
62
  See the **cratis-components-styling** skill for the full theming contract.
61
63
 
62
64
  ## Step 2 — The DataPage shell
@@ -81,9 +83,9 @@ export const AccountsPage = () => (
81
83
  );
82
84
  ```
83
85
 
84
- Only `DataPage.Columns` and `DataPage.MenuItems` exist as compound members.
85
- `MenuItem` and `Column` are **named exports** — there is no `DataPage.MenuItem`
86
- and no `DataPage.Column`. Pass `dataKey` whenever the read model has an
86
+ `DataPage.Columns`, `DataPage.MenuItems` and `DataPage.MenuItem` are the
87
+ compound members; `MenuItem` and `Column` are also **named exports** of the
88
+ subpath (there is no `DataPage.Column`). Pass `dataKey` whenever the read model has an
87
89
  identity.
88
90
 
89
91
  See [data-page.md](references/data-page.md) for every prop, and
@@ -97,6 +99,7 @@ Menu items go in `<DataPage.MenuItems>`. `MenuItem` takes `command`, not
97
99
  string. `disableOnUnselected` greys the item out until a row is selected.
98
100
 
99
101
  ```tsx
102
+ import { FaPencil, FaPlus } from 'react-icons/fa6';
100
103
  import { DataPage, MenuItem } from '@cratis/components/DataPage';
101
104
  import { useDialog } from '@cratis/arc.react/dialogs';
102
105
  import { CreateAccountDialog } from './CreateAccountDialog';
@@ -105,8 +108,8 @@ const [CreateAccountWrapper, showCreateAccount] = useDialog(CreateAccountDialog)
105
108
 
106
109
  <DataPage title='Accounts' query={AllAccounts} emptyMessage='No accounts yet.'>
107
110
  <DataPage.MenuItems>
108
- <MenuItem label='Add account' icon={() => <i className='pi pi-plus' />} command={() => showCreateAccount()} />
109
- <MenuItem label='Edit account' icon={() => <i className='pi pi-pencil' />} command={() => showEditAccount()} disableOnUnselected />
111
+ <MenuItem label='Add account' icon={FaPlus} command={() => showCreateAccount()} />
112
+ <MenuItem label='Edit account' icon={FaPencil} command={() => showEditAccount()} disableOnUnselected />
110
113
  </DataPage.MenuItems>
111
114
  <DataPage.Columns>
112
115
  <Column field='name' header='Name' />
@@ -146,9 +149,9 @@ export const CreateAccountDialog = () => {
146
149
  };
147
150
  ```
148
151
 
149
- Never put a raw PrimeReact control inside a command dialog for a command value —
150
- it bypasses the field wrapper, so validation never re-runs and the submit button
151
- stays disabled. Seed values that must be present for validity with
152
+ Never put a raw control (a `Common` `TextInput`, a native `<input>`) inside a
153
+ command dialog for a command value — it is not bound to the command, so
154
+ validation never re-runs and the submit button stays disabled. Seed values that must be present for validity with
152
155
  `initialValues`, not `onBeforeExecute`.
153
156
 
154
157
  ## Step 5 — Confirming, and showing that work is in progress
@@ -5,19 +5,21 @@ optional details pane in one component. Import from
5
5
  `@cratis/components/DataPage`.
6
6
 
7
7
  ```tsx
8
+ import { FaPlus } from 'react-icons/fa6';
8
9
  import { Column, DataPage, MenuItem } from '@cratis/components/DataPage';
9
10
  import type { IDetailsComponentProps } from '@cratis/components/DataPage';
10
11
  ```
11
12
 
12
13
  ## Compound members
13
14
 
14
- Exactly two static members exist:
15
+ Three static members exist:
15
16
 
16
17
  - `DataPage.Columns` — wraps the `Column` elements.
17
18
  - `DataPage.MenuItems` — wraps the `MenuItem` elements.
19
+ - `DataPage.MenuItem` — the same component as the named `MenuItem` export.
18
20
 
19
21
  `Column` and `MenuItem` are named exports of the same subpath. There is no
20
- `DataPage.Column` and no `DataPage.MenuItem`.
22
+ `DataPage.Column`.
21
23
 
22
24
  ## `DataPageProps`
23
25
 
@@ -37,9 +39,10 @@ Exactly two static members exist:
37
39
  | `onRefresh` | `() => void` | invoked to re-fetch a snapshot query |
38
40
  | `actionsAriaLabel` | `string` | accessible name of the actions menubar, default `'Actions'` |
39
41
  | `tableClassName` | `string` | class on the inner table |
40
- | `tablePt` / `tablePtOptions` / `tableUnstyled` | PrimeReact pass-through | target the inner data table |
42
+ | `tablePt` | `DataTableParts` | per-part attributes on the inner data table (`tablePtOptions`/`tableUnstyled` are accepted no-ops) |
41
43
  | `menubarClassName` | `string` | class on the action menubar |
42
- | `menubarPt` / `menubarPtOptions` / `menubarUnstyled` | PrimeReact pass-through | target the action buttons |
44
+ | `menubarPt` | `ButtonParts` | per-part attributes on the action buttons (`menubarPtOptions`/`menubarUnstyled` are accepted no-ops) |
45
+ | `paginatorPt` | `TablePaginatorParts` | per-part attributes on the paginator |
43
46
  | `clientFiltering` | `boolean` | **deprecated and a no-op** — do not use in new code |
44
47
 
45
48
  ## Snapshot versus observable
@@ -64,7 +67,7 @@ after a command succeeds.
64
67
  reads. Icons are usually a small inline component:
65
68
 
66
69
  ```tsx
67
- <MenuItem label='Add account' icon={() => <i className='pi pi-plus' />} command={() => showCreate()} />
70
+ <MenuItem label='Add account' icon={FaPlus} command={() => showCreate()} />
68
71
  ```
69
72
 
70
73
  ## `IDetailsComponentProps<TDataType>`
@@ -99,7 +102,8 @@ declaration the table reads.
99
102
  | `showFilterMatchModes` | `boolean` |
100
103
  | `filterElement` | `(options: ColumnFilterElementOptions) => ReactNode` |
101
104
  | `filterLabels` | `Partial<ColumnFilterMenuLabels>` |
102
- | `selectionMode` | `'single' \| 'multiple'` |
105
+ | `filterPt` | `ColumnFilterMenuParts` — parts of the filter popup |
106
+ | `selectionMode` | `'single'` — the only implemented value; there is no checkbox multi-selection |
103
107
  | `style` / `className` | `React.CSSProperties` / `string` |
104
108
  | `headerStyle` / `headerClassName` | `React.CSSProperties` / `string` |
105
109
  | `bodyStyle` / `bodyClassName` | `React.CSSProperties` / `string` |
@@ -112,11 +116,11 @@ Use `body` for a computed or formatted cell:
112
116
 
113
117
  ## Type name caution
114
118
 
115
- `@cratis/components/DataPage` exports two different things called
116
- `ColumnProps` — the props of the `DataPage.Columns` wrapper and the re-exported
117
- column declaration props. Import `ColumnProps` from
118
- `@cratis/components/DataTables` when you need the column type, so the reference
119
- is unambiguous.
119
+ `ColumnProps` from `@cratis/components/DataPage` is the **column declaration**
120
+ type re-exported from `DataTables` (the explicit named re-export shadows the
121
+ `DataPage.Columns` wrapper's own `ColumnProps`, which is not reachable from the
122
+ subpath). Import it from `@cratis/components/DataTables` when you want the
123
+ reference to say so.
120
124
 
121
125
  ## Layout
122
126
 
@@ -40,7 +40,8 @@ Both components take the same prop names:
40
40
  | `globalFilterFields` | `string[] \| undefined` | enables the search box |
41
41
  | `defaultFilters` | `DataTableFilterMeta` | initial filter state |
42
42
  | `className` | `string` | |
43
- | `pt` / `ptOptions` / `unstyled` | PrimeReact pass-through | |
43
+ | `pt` | `DataTableParts` | per-part attributes (`ptOptions`/`unstyled` are accepted no-ops) |
44
+ | `paginatorPt` | `TablePaginatorParts` | per-part attributes on the paginator |
44
45
  | `paginatorClassName` | `string` | |
45
46
  | `paginatorAriaLabels` | paginator label overrides | localize the paginator |
46
47
  | `clientFiltering` | `boolean` | **deprecated and a no-op** |
@@ -58,7 +59,13 @@ Both components take the same prop names:
58
59
  </DataTableForQuery>
59
60
  ```
60
61
 
61
- ## Paging
62
+ ## Paging, sorting and filtering scope
63
+
64
+ Column sorting and filtering — and the search box — apply to the **currently
65
+ loaded page**, not the complete result. Complete-result filtering and sorting
66
+ belong in the query's arguments and in the server-side query, before paging;
67
+ `clientFiltering` does not change this and is a deprecated no-op. Server totals
68
+ remain authoritative for the paginator.
62
69
 
63
70
  Both tables page server-side through the Arc paging hooks with a fixed page
64
71
  size of 20 rows starting at page 0. The paginator renders only when the result
@@ -1,7 +1,7 @@
1
1
  # Dialogs reference
2
2
 
3
3
  The Cratis dialog wrappers own command execution, validation timing, busy
4
- state, and footer buttons. Never import `Dialog` from `primereact/dialog`.
4
+ state, and footer buttons. Never use a vendor or hand-rolled modal — dialogs are Components-owned.
5
5
 
6
6
  The **components** live in `@cratis/components`; the **hooks, enums, and
7
7
  context** live in `@cratis/arc.react/dialogs`. `@cratis/components` exports no
@@ -41,10 +41,11 @@ first two is the normal case. `showDialog(input?)` resolves to
41
41
  `[DialogResult, TResponse?]` when the dialog closes.
42
42
 
43
43
  Inside the dialog, prefer plain typed props for input and take `closeDialog`
44
- from `useDialogContext<TResponse>()`:
44
+ from `useDialogContext<TRequest, TResponse>()` — the **first** type parameter is
45
+ the request the dialog was shown with, the second the response it closes with:
45
46
 
46
47
  ```tsx
47
- const { request, closeDialog } = useDialogContext<AccountCreated>();
48
+ const { request, closeDialog } = useDialogContext<object, AccountCreated>();
48
49
  closeDialog(DialogResult.Ok, response);
49
50
  ```
50
51
 
@@ -86,7 +87,7 @@ The most-used props:
86
87
  | `validateOnInit` | validate on mount so pre-filled invalid values show immediately |
87
88
  | `initialFocus` | which control receives focus when the dialog opens |
88
89
  | `dismissable` | X, Escape, and backdrop dismissal |
89
- | `pt` / `ptOptions` / `unstyled` | PrimeReact pass-through |
90
+ | `pt` | `DialogParts` — per-part attributes (`backdrop`, `positioner`, `root`, `header`, `title`, `close`, `content`, `footer`, `confirm`, `cancel`); `ptOptions`/`unstyled` are accepted no-ops |
90
91
 
91
92
  `CommandDialog.Column` exists for multi-column layouts:
92
93
 
@@ -132,8 +133,8 @@ wrapper close. Do not use `onConfirm` as a result handler.
132
133
 
133
134
  Every user-entered command value must be bound through a `CommandForm` field
134
135
  from `@cratis/components/CommandForm` (also published as
135
- `@cratis/components/CommandForm/fields`, the same module). A raw PrimeReact
136
- control bypasses the field wrapper, so validation never re-runs and the submit
136
+ `@cratis/components/CommandForm/fields`, the same module). A raw control (a
137
+ `Common` `TextInput`, a native `<input>`) is not bound to the command, so validation never re-runs and the submit
137
138
  button stays disabled.
138
139
 
139
140
  The full catalog: `InputTextField`, `PasswordField`, `NumberField`,
@@ -173,7 +174,7 @@ property descriptors, with `exclude` for the ones you do not want:
173
174
 
174
175
  ```tsx
175
176
  export const RenameDialog = () => {
176
- const { closeDialog } = useDialogContext<{ name: string }>();
177
+ const { closeDialog } = useDialogContext<object, { name: string }>();
177
178
  const [name, setName] = useState('');
178
179
 
179
180
  return (
@@ -197,9 +198,10 @@ when omitted, `isBusy` `false`, `okLabel` `'Ok'`, `cancelLabel` `'Cancel'`,
197
198
  Two behaviors worth knowing:
198
199
 
199
200
  - `resizable` is accepted for compatibility but has **no effect** — the
200
- PrimeReact 11 headless dialog has no resize.
201
+ Components dialog has no resize.
201
202
  - Passing a custom node to `buttons` instead of a `DialogButtons` member
202
- removes the header close control, disables Escape, and means `onClose`,
203
+ removes the header close control and disables Escape/backdrop dismissal
204
+ (unless you also pass `dismissable` explicitly), and means `onClose`,
203
205
  `onCancel`, and `onConfirm` are never invoked. Close through
204
206
  `useDialogContext().closeDialog(...)`, or set `dismissable` explicitly.
205
207
 
@@ -48,6 +48,30 @@ Guard rendering with `hasData` rather than checking `data.length` — a
48
48
  conditional query that has not fired returns an empty result with
49
49
  `hasData: false`.
50
50
 
51
+ ### Command success is not projection convergence
52
+
53
+ A successful `CommandResult` means the events were **appended**. The read model a
54
+ query reads is built by an observer that runs *after* that, so for a moment the
55
+ command has succeeded and the query still answers from before it. Model the
56
+ states separately instead of collapsing them into "loaded or not":
57
+
58
+ | State | Signal | Render |
59
+ | --- | --- | --- |
60
+ | Not asked yet | `.when(false)` / `!isReady` | nothing, or the previous content |
61
+ | Pending | `isPerforming`, or `hasData: false` **right after a command you just issued succeeded** | a skeleton — **never** "not found" |
62
+ | Converged, empty | `hasData` with an empty `data` and no recent command | the designed empty state |
63
+ | Converged, populated | `hasData` with items | the content |
64
+ | Failed | `!isSuccess` / `hasExceptions` / `!isAuthorized` | the matching error affordance |
65
+ | Stale refresh | `isPerforming` while `data` still holds the previous result | keep the old content, indicate refresh |
66
+
67
+ Two consequences. After a create command, take the **window action on the
68
+ command's success** (close the dialog, navigate to the new id) and let the list
69
+ catch up — do not wait for the query to show the row before closing. And for a
70
+ detail page opened on an id you just created, `hasData: false` is *pending*, not
71
+ *missing*: an observable query (`ISubject<T>` on the backend, `.use()` here)
72
+ resolves it the moment the projection lands, which is why observable reads are
73
+ the default for anything a user changes and then looks at.
74
+
51
75
  ### Paging
52
76
 
53
77
  ```ts
@@ -196,5 +220,5 @@ query transport. Its props include `microservice`, `origin`, `basePath`,
196
220
  `apiBasePath`, `httpHeadersCallback` (merged into every request — bearer and
197
221
  tenant headers), `detailsType`, `queryTransportMethod`, `queryConnectionCount`,
198
222
  `queryDirectMode`, `observableQueryTransferMode`, and `queryCacheRetentionMs`.
199
- `QueryTransportMethod` and `ObservableQueryTransferMode` import from
200
- `@cratis/arc`; `Arc` imports from `@cratis/arc.react`.
223
+ `QueryTransportMethod` imports from `@cratis/arc/queries`,
224
+ `ObservableQueryTransferMode` from `@cratis/arc`; `Arc` imports from `@cratis/arc.react`.
@@ -16,8 +16,10 @@ This skill is verified against these exact sources:
16
16
 
17
17
  | Package | Version | Purpose |
18
18
  | --- | --- | --- |
19
- | `Cratis.Cli` | `2.4.0` | the `cratis` command, its contexts, output formats, and command tree |
20
- | `Cratis.Chronicle` | `16.45.2` | the observer, partition, sequence, and job concepts the CLI reads |
19
+ | `Cratis.Cli` | `3.2.0` | the `cratis` command, its contexts, output formats, and command tree |
20
+
21
+ > Re-verified at `Cratis/cli` **v3.2.0** (originally written against 2.4.0): every command, branch, flag and output format this skill names exists there; the 2.x→3.x change is the Chronicle 17/18 wire migration plus new branches (`ai`, `arc`, `screenplay`, `prologue`, `llm`) this skill does not cover.
22
+ | `Cratis.Chronicle` | `18.3.0` | the observer, partition, sequence, and job concepts the CLI reads |
21
23
 
22
24
  The CLI ships a **versioned machine-readable catalog of its own surface**, and
23
25
  that catalog is the authority for exact command names on the installed version:
@@ -110,7 +112,7 @@ error.
110
112
  | Is the server healthy at all? | `cratis chronicle diagnose` (exit code 3 when unhealthy) |
111
113
  | Why has this read model stopped updating? | `chronicle failed-partitions list --observer <id>` — the error is on the partition, not in the log |
112
114
  | An observer is quarantined — why? | `chronicle failed-partitions show <observer> <partition> --detailed`, with attempt history |
113
- | Did this event actually get appended? | `chronicle events get --event-type <type> --event-source-id <id>`, or `chronicle events tail` |
115
+ | Did this event actually get appended? | `chronicle events get --event-type <type> --event-source-id <id>` (`events tail` returns only the highest sequence number — not a count, not the events) |
114
116
  | What is this event's shape in the store? | `chronicle event-types list`, then `chronicle event-types show <type>` |
115
117
  | Is this projection registered? | `chronicle projections list`, then `chronicle projections show <id>` |
116
118
  | What does the read model actually hold? | `chronicle read-models get <read-model> <key>`, or `read-models instances` |
@@ -165,16 +167,20 @@ Before any of them:
165
167
 
166
168
  ### Two confirmation traps
167
169
 
168
- **Confirmation prompts do not fire when stdout is not a terminal.** The CLI
169
- treats a non-interactive session as an implicit yes, so a destructive command
170
- run from a script, a pipeline, or an agent harness proceeds without `-y` and
171
- without asking. Never rely on the prompt as the safety mechanism — the
172
- authorization above is the safety mechanism.
173
-
174
- **Not every mutating command prompts, even interactively.** `jobs stop` and
175
- `jobs resume` describe themselves as prompting for confirmation, but no prompt
176
- exists in the implementation. `users add`, `applications add`, and
177
- `subscriptions add` do not prompt either.
170
+ **Destructive commands fail closed outside a terminal.** Every command with a
171
+ confirmation prompt — `observers replay`, `observers replay-partition`,
172
+ `observers retry-partition`, `observers clear-quarantine`, `jobs stop`,
173
+ `jobs resume`, `recommendations perform`, `recommendations ignore`,
174
+ `users remove`, `applications remove`, `subscriptions remove` — asks
175
+ interactively, and when the session is **not** interactive (a script, a
176
+ pipeline, an agent harness) it does *not* proceed: it writes
177
+ "Re-run the command with --yes to confirm the operation" and exits with the
178
+ validation error code. `--yes` is therefore the only way a non-interactive run
179
+ performs one of these, which makes `--yes` the authorization boundary. Declining
180
+ the interactive prompt exits successfully having done nothing.
181
+
182
+ **Additive commands do not prompt.** `users add`, `applications add` and
183
+ `subscriptions add` run without confirmation in every mode.
178
184
 
179
185
  Reaching for `--yes` to silence a prompt you have not read is how the wrong
180
186
  store gets replayed. A failed partition you have not yet explained is not a
@@ -17,16 +17,18 @@ There is no host requirement and no application architecture imposed.
17
17
  ## Verified product sources
18
18
 
19
19
  This skill is verified against the `Cratis/Chronicle` repository at tag
20
- `v17.0.1`, whose client sources are byte-identical to `16.45.2` for every public
21
- type cited here except the compatibility check noted below.
20
+ `v18.3.0`. Its client sources are unchanged in public shape since `v17.0.1`
21
+ (the 17→18 client diff is converters, options and doc comments), and `v17.0.1`
22
+ was byte-identical to `16.45.2` for every public type cited here except the
23
+ compatibility check noted below.
22
24
 
23
25
  | Package | Line | Purpose |
24
26
  | --- | --- | --- |
25
- | `Cratis.Chronicle` | `17.x` | `ChronicleClient`, `IEventStore`, `[EventType]`, observers |
26
- | `Cratis.Chronicle.Connections` | `17.x` | `ChronicleConnectionString`, connection lifecycle |
27
- | `Cratis.Chronicle.AspNetCore` | `17.x` | ASP.NET Core wiring, header/subdomain namespace resolvers |
28
- | `Cratis.Chronicle.Testing` | `17.x` | in-process scenarios |
29
- | `Cratis.Chronicle.CodeAnalysis` | `17.x` | the analyzers, a **separate opt-in** package |
27
+ | `Cratis.Chronicle` | `18.3.0` | `ChronicleClient`, `IEventStore`, `[EventType]`, observers |
28
+ | `Cratis.Chronicle.Connections` | `18.3.0` | `ChronicleConnectionString`, connection lifecycle |
29
+ | `Cratis.Chronicle.AspNetCore` | `18.3.0` | ASP.NET Core wiring, header/subdomain namespace resolvers |
30
+ | `Cratis.Chronicle.Testing` | `18.3.0` | in-process scenarios |
31
+ | `Cratis.Chronicle.CodeAnalysis` | `18.3.0` | the analyzers, a **separate opt-in** package |
30
32
 
31
33
  Take the exact version from nuget.org. The version in source is a `1.0.0`
32
34
  placeholder injected at pack time (`Source/Directory.Build.props`), so the
@@ -182,23 +184,23 @@ and an optional `EventStoreNamespaceResolverType`.
182
184
  Since Chronicle 17 the compatibility check is a server-side RPC, and **the client
183
185
  runs it automatically inside `Connect()`** —
184
186
  `Source/Clients/Connections/ChronicleConnection.cs:310` calls
185
- `CheckCompatibility` (`:405`), sending the client type, client version, protocol
186
- version, and the descriptor set its contracts package was built with (`:411-417`).
187
- The rationale is at `:400-404`: Chronicle has clients in four languages and only
187
+ `CheckCompatibility` (`:414`), sending the client type, client version, protocol
188
+ version, and the descriptor set its contracts package was built with (`:420-426`).
189
+ The rationale is at `:409-413`: Chronicle has clients in four languages and only
188
190
  some can build a descriptor set at runtime, so each ships the one it was built
189
191
  with and the server does the single comparison.
190
192
 
191
193
  Behavior you can rely on:
192
194
 
193
195
  - A server too old to have the RPC answers `Unimplemented`, and the client falls
194
- back to the previous client-side exchange (`:419-425`) — upgrading the client
196
+ back to the previous client-side exchange (`:428-434`) — upgrading the client
195
197
  does not silently drop the check.
196
- - Any other transport error is **logged and ignored** (`:426-432`), on the stated
198
+ - Any other transport error is **logged and ignored** (`:435-441`), on the stated
197
199
  reasoning that failing to ask says nothing about whether the two sides agree.
198
200
  - A genuine mismatch throws `IncompatibleServerException`
199
201
  (`Source/Clients/Connections/IncompatibleServerException.cs:10`) whose message
200
202
  names the server address, its version, its protocol version, and the specific
201
- incompatibilities (`:436-443`).
203
+ incompatibilities (`:443-449`).
202
204
 
203
205
  The client identifies itself as `".NET"`
204
206
  (`Source/Clients/Connections/ChronicleClientIdentity.cs:22`) with its assembly
@@ -333,8 +335,8 @@ Read models are queried through `eventStore.ReadModels`
333
335
  Artifacts are found by **assembly scanning**, with no registration call and no DI
334
336
  container required. `DefaultClientArtifactsProvider.Default` composes the
335
337
  project-referenced and package-referenced assemblies
336
- (`Source/Clients/DotNET/DefaultClientArtifactsProvider.cs:35`), and the
337
- predicates are exactly (`:230-238`):
338
+ (`Source/Clients/DotNET/DefaultClientArtifactsProvider.cs:37`), and the
339
+ predicates are exactly (`:242-251`):
338
340
 
339
341
  | Kind | Predicate |
340
342
  | --- | --- |