From 13f6e03a9508688538bfcf36f635d936c9b9615e Mon Sep 17 00:00:00 2001 From: cratis-distribution-fixture-bot Date: Tue, 1 Sep 2026 21:33:03 +0200 Subject: [PATCH] Generate public marketplace distribution 0.2.1 Add the required OpenAI publisher interface assets and current corpus bytes while preserving exact marketplace checks and no-support boundaries. --- .claude-plugin/marketplace.json | 4 +- .cursor-plugin/marketplace.json | 4 +- .github/plugin/marketplace.json | 4 +- README.md | 6 +- SHA256SUMS | 38 +++++----- assets/cratis-logo.png | Bin 0 -> 8035 bytes distribution-manifest.json | 66 ++++++++++-------- gemini-extension.json | 2 +- marketplace-release.json | 4 +- package.json | 2 +- plugin.json | 2 +- .../.claude-plugin/plugin.json | 2 +- .../.codex-plugin/plugin.json | 29 +++++++- .../public-cratis-ai/assets/cratis-logo.png | Bin 0 -> 8035 bytes plugins/public-cratis-ai/plugin.json | 2 +- .../skills/cratis-react-page/SKILL.md | 34 ++++++++- .../skills/event-type-migrations/SKILL.md | 23 +++++- provenance.json | 27 +++++-- skills/cratis-react-page/SKILL.md | 34 ++++++++- skills/event-type-migrations/SKILL.md | 23 +++++- submissions/cursor.json | 2 +- submissions/openai.json | 7 +- 22 files changed, 237 insertions(+), 78 deletions(-) create mode 100644 assets/cratis-logo.png create mode 100644 plugins/public-cratis-ai/assets/cratis-logo.png diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index f5c3412..faed169 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -5,13 +5,13 @@ }, "metadata": { "description": "Cratis AI skills for event-sourced and CQRS application development", - "version": "0.2.0" + "version": "0.2.1" }, "plugins": [ { "name": "public-cratis-ai", "description": "Cratis AI skills for event-sourced and CQRS application development", - "version": "0.2.0", + "version": "0.2.1", "source": "./plugins/public-cratis-ai", "strict": true } diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json index 68e5c9c..2a092b4 100644 --- a/.cursor-plugin/marketplace.json +++ b/.cursor-plugin/marketplace.json @@ -5,13 +5,13 @@ }, "metadata": { "description": "Cratis AI skills for event-sourced and CQRS application development", - "version": "0.2.0" + "version": "0.2.1" }, "plugins": [ { "name": "public-cratis-ai", "description": "Cratis AI skills for event-sourced and CQRS application development", - "version": "0.2.0", + "version": "0.2.1", "source": "./plugins/public-cratis-ai" } ] diff --git a/.github/plugin/marketplace.json b/.github/plugin/marketplace.json index f5c3412..faed169 100644 --- a/.github/plugin/marketplace.json +++ b/.github/plugin/marketplace.json @@ -5,13 +5,13 @@ }, "metadata": { "description": "Cratis AI skills for event-sourced and CQRS application development", - "version": "0.2.0" + "version": "0.2.1" }, "plugins": [ { "name": "public-cratis-ai", "description": "Cratis AI skills for event-sourced and CQRS application development", - "version": "0.2.0", + "version": "0.2.1", "source": "./plugins/public-cratis-ai", "strict": true } diff --git a/README.md b/README.md index 44224f9..c48fcd2 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Passive skills for building event-sourced and CQRS applications with Cratis. ### OpenAI Codex CLI ```bash -codex plugin marketplace add Cratis/AI.Distribution --ref v0.2.0 +codex plugin marketplace add Cratis/AI.Distribution --ref v0.2.1 codex plugin add public-cratis-ai@cratis ``` @@ -28,7 +28,7 @@ copilot plugin install public-cratis-ai@cratis ### Gemini CLI ```bash -gemini extensions install https://github.com/Cratis/AI.Distribution --ref v0.2.0 +gemini extensions install https://github.com/Cratis/AI.Distribution --ref v0.2.1 ``` ### Kiro @@ -38,7 +38,7 @@ Choose **Add Custom Power**, then import `https://github.com/Cratis/AI.Distribut ### Pi ```bash -pi install git:github.com/Cratis/AI.Distribution@v0.2.0 +pi install git:github.com/Cratis/AI.Distribution@v0.2.1 ``` ### Generic Agent Skills and Agent Plugins diff --git a/SHA256SUMS b/SHA256SUMS index d84d5e5..865b7df 100644 --- a/SHA256SUMS +++ b/SHA256SUMS @@ -1,16 +1,18 @@ 96441cce905ac08d53aa6842f12e400ead370bbe39ccfd05cc0b9143f4cf0ef5 .agents/plugins/marketplace.json -e3a18b82c3e84f50820b4bcb9ad752b44d2777af73a18100084f70f3385e44a8 .claude-plugin/marketplace.json -da448ca1bb5ede9e0fb5348338d60c5607479371c6279d17ce15d6a813aa00ec .cursor-plugin/marketplace.json -e3a18b82c3e84f50820b4bcb9ad752b44d2777af73a18100084f70f3385e44a8 .github/plugin/marketplace.json +8074fd4efb7aef4315abcef4351ebe917b3201b9f229051aacfc090da9ae764d .claude-plugin/marketplace.json +8c91b25bfc705a2f4cfbc83c349ef8ea192fe723e31e58e973531301a74c49f9 .cursor-plugin/marketplace.json +8074fd4efb7aef4315abcef4351ebe917b3201b9f229051aacfc090da9ae764d .github/plugin/marketplace.json 8db23da452b8cee0e9aa8d49801000475bbcc30ab4e6e322e28d1146df7230a7 LICENSE -5d7beef5fba80029f16674ad9b2f80144ddddabc594909cbf5febf26868c5894 README.md -421fc89f770174950d14116643783d3446ab793c99ddb05cd9d7ea053d4acf75 gemini-extension.json -cecdd773207c9e88fb377491fdca35ee511f523320009161739d220052296887 marketplace-release.json -97f6394890220eb53eab3ecab2a2a1a652cec4fecbe7e10724054e2d77a06516 package.json -41b5d4892c55581e330a57accdbb2021b7b3f86130f4b1956d48185e09ac5d3a plugin.json -a9a78f1c5719a74c4edafab5f71e31748cecd4502d57b00f94654198afdf8765 plugins/public-cratis-ai/.claude-plugin/plugin.json -5e3610dee0f0d399a32d425551fbcdab81449248e6088a9f321b8239429c9e6b plugins/public-cratis-ai/.codex-plugin/plugin.json -41b5d4892c55581e330a57accdbb2021b7b3f86130f4b1956d48185e09ac5d3a plugins/public-cratis-ai/plugin.json +d2cf28e491761651bdddd62f6e18b8a039e5a07c3061c4877c604ab5671928e8 README.md +da99d76b1513c92617e4f3104437fe8988a3b94cc27d457955eb7e155403b7f6 assets/cratis-logo.png +40ead36f9f411b8cd5751cbf817249eda647c0beb3389b5bc1b2a72c2e1b8ec4 gemini-extension.json +2316f761d8eae37b21c6245ed7503982d52bf40502e7320f613021fefeb6af9d marketplace-release.json +3205023f00f4b0bf9064725cf6cc40d5206a6981b1a8347a9afafa771c74d47e package.json +d6b793178c14f790fddb7aa8576bfadf70fd47927107eec3f92198093ae413e1 plugin.json +03eb2fd09c658a3bbd5771574b304068d048ff9653255dec29ee63f76baee6ac plugins/public-cratis-ai/.claude-plugin/plugin.json +8216d19f8f3f32901bc6d4d7453b05a54ec07aeb2fb9122683938dbf0a3da1ca plugins/public-cratis-ai/.codex-plugin/plugin.json +da99d76b1513c92617e4f3104437fe8988a3b94cc27d457955eb7e155403b7f6 plugins/public-cratis-ai/assets/cratis-logo.png +d6b793178c14f790fddb7aa8576bfadf70fd47927107eec3f92198093ae413e1 plugins/public-cratis-ai/plugin.json e94076cb3fc215d2e358aa095be6a0490c04d37de2b4d8f6ac57afe0862e9456 plugins/public-cratis-ai/skills/add-business-rule/SKILL.md d4e9952cb7042e33ee1c5547e64ebd58a8a6dd837843f72ba4cd002eb3b7e5f0 plugins/public-cratis-ai/skills/add-ef-migration/SKILL.md e6c53b655a689a043785846b0842e4845397ac7aca706e724c0102dea45558d2 plugins/public-cratis-ai/skills/add-projection/SKILL.md @@ -31,7 +33,7 @@ d8ebd3270d193ec743d74f80ace55cb57ff0eabbcef41419e9432efa233fa914 plugins/public 6ef7a29ac797cf16b0c43a34d7e859597638be739d4876b1748958d93179011a plugins/public-cratis-ai/skills/cratis-command/references/validation.md 91062c99a13a9ae1cf4097be14c33b031b6b6944c79388753c6ddb0e98339d63 plugins/public-cratis-ai/skills/cratis-fundamentals-concept/LICENSE 423ab2d27b08e13d3c7c3fbaf9bbc06ea1fb9a13610bdcfdf37398b12d593ec9 plugins/public-cratis-ai/skills/cratis-fundamentals-concept/SKILL.md -7dfe2eb8a8336f5b3f65af79105d07427b55cc651fac93fa979f42a6878b7f08 plugins/public-cratis-ai/skills/cratis-react-page/SKILL.md +e623dacbc6a3114236b70257046ac8445a4432c8fa7be16ac07bd7b59e3b165b plugins/public-cratis-ai/skills/cratis-react-page/SKILL.md d98695778cda0b5281ff0386165869023314d957cb89bfc100ad6a52fe907407 plugins/public-cratis-ai/skills/cratis-react-page/references/data-page.md 6f3cdc12c81f9af67abed46ed4c698eb2a66691e9bed6a04d65d605b7445351e plugins/public-cratis-ai/skills/cratis-react-page/references/data-table.md a646df0fdd1a026e9c424eb823e5104d9482617dd8c6674d3756ce81309dd317 plugins/public-cratis-ai/skills/cratis-react-page/references/dialogs.md @@ -55,7 +57,7 @@ a5d90be9cfc37ac2a0c7b51a8a69fce815fb744e801ea94619dff96553a41045 plugins/public 45839e11e7aa7c2b66e93a2b83b2cef964aa2aa8abeb9064a9505c90677e95ea plugins/public-cratis-ai/skills/diagnose-slice/SKILL.md 907a0f4f3d06856b07f10c1465a7bc2c515d8ec27b0cb84ba335a217f7290cf0 plugins/public-cratis-ai/skills/discover-implementations/SKILL.md 4cc24ccf0faf14066dad477aa87732a6e593ef263c9e0f377b1c9be59ed32f27 plugins/public-cratis-ai/skills/event-modeling/SKILL.md -eec56904897163d9261d3ec976595956fa089a717c7854837ef318e75e387412 plugins/public-cratis-ai/skills/event-type-migrations/SKILL.md +459d68ef45d14b647d7523acf8177f698e798555b62eb1ae79d31cd50f1379cc plugins/public-cratis-ai/skills/event-type-migrations/SKILL.md d896c80b4a95a3517fbc66b9fc169c9a11b82096448cb1e7ce5a8a9e51d11aa3 plugins/public-cratis-ai/skills/inspect-running-chronicle/SKILL.md d88b6633208c7ce3dddb629567db8df2fcfda351c4191b326cee7c382f75ed31 plugins/public-cratis-ai/skills/multi-tenancy/SKILL.md 657c4b0d399a3e9d282210db7ff9d539fa5437bfbc40096f6df544aa965d80b3 plugins/public-cratis-ai/skills/new-vertical-slice/SKILL.md @@ -73,7 +75,7 @@ bb8e4a571f2814fe5b56ae6cb33a75e21b6484d80e7c5d3f340b0f185c11c68f plugins/public 57d0f2511e950edf8b390a2b5c44cd4532a6aa258d78e8bffc7167a6449dc054 plugins/public-cratis-ai/skills/write-specs-readmodels/SKILL.md e6bc79cd003e97c591dc0c12c7aa727b809f0e7a8ac9e5d05ad7ab6d79dc8c0e plugins/public-cratis-ai/skills/write-specs/SKILL.md 6dc9b60a7a088c2a9860f4518c5256076b3b3256dd763b237aac05558787b03a plugins/public-cratis-ai/skills/write-specs/references/EXAMPLES.md -4af274b470b4837164d1afd4a4b79bc835f5fcd3a3709cc10c2c0132eca06456 provenance.json +e678f653db17e4195685c6e0caba23ca5c1a1974f67c0f5489dc541d6ebdc612 provenance.json e94076cb3fc215d2e358aa095be6a0490c04d37de2b4d8f6ac57afe0862e9456 skills/add-business-rule/SKILL.md d4e9952cb7042e33ee1c5547e64ebd58a8a6dd837843f72ba4cd002eb3b7e5f0 skills/add-ef-migration/SKILL.md e6c53b655a689a043785846b0842e4845397ac7aca706e724c0102dea45558d2 skills/add-projection/SKILL.md @@ -94,7 +96,7 @@ d8ebd3270d193ec743d74f80ace55cb57ff0eabbcef41419e9432efa233fa914 skills/cratis- 6ef7a29ac797cf16b0c43a34d7e859597638be739d4876b1748958d93179011a skills/cratis-command/references/validation.md 91062c99a13a9ae1cf4097be14c33b031b6b6944c79388753c6ddb0e98339d63 skills/cratis-fundamentals-concept/LICENSE 423ab2d27b08e13d3c7c3fbaf9bbc06ea1fb9a13610bdcfdf37398b12d593ec9 skills/cratis-fundamentals-concept/SKILL.md -7dfe2eb8a8336f5b3f65af79105d07427b55cc651fac93fa979f42a6878b7f08 skills/cratis-react-page/SKILL.md +e623dacbc6a3114236b70257046ac8445a4432c8fa7be16ac07bd7b59e3b165b skills/cratis-react-page/SKILL.md d98695778cda0b5281ff0386165869023314d957cb89bfc100ad6a52fe907407 skills/cratis-react-page/references/data-page.md 6f3cdc12c81f9af67abed46ed4c698eb2a66691e9bed6a04d65d605b7445351e skills/cratis-react-page/references/data-table.md a646df0fdd1a026e9c424eb823e5104d9482617dd8c6674d3756ce81309dd317 skills/cratis-react-page/references/dialogs.md @@ -118,7 +120,7 @@ a5d90be9cfc37ac2a0c7b51a8a69fce815fb744e801ea94619dff96553a41045 skills/cratis- 45839e11e7aa7c2b66e93a2b83b2cef964aa2aa8abeb9064a9505c90677e95ea skills/diagnose-slice/SKILL.md 907a0f4f3d06856b07f10c1465a7bc2c515d8ec27b0cb84ba335a217f7290cf0 skills/discover-implementations/SKILL.md 4cc24ccf0faf14066dad477aa87732a6e593ef263c9e0f377b1c9be59ed32f27 skills/event-modeling/SKILL.md -eec56904897163d9261d3ec976595956fa089a717c7854837ef318e75e387412 skills/event-type-migrations/SKILL.md +459d68ef45d14b647d7523acf8177f698e798555b62eb1ae79d31cd50f1379cc skills/event-type-migrations/SKILL.md d896c80b4a95a3517fbc66b9fc169c9a11b82096448cb1e7ce5a8a9e51d11aa3 skills/inspect-running-chronicle/SKILL.md d88b6633208c7ce3dddb629567db8df2fcfda351c4191b326cee7c382f75ed31 skills/multi-tenancy/SKILL.md 657c4b0d399a3e9d282210db7ff9d539fa5437bfbc40096f6df544aa965d80b3 skills/new-vertical-slice/SKILL.md @@ -136,5 +138,5 @@ bb8e4a571f2814fe5b56ae6cb33a75e21b6484d80e7c5d3f340b0f185c11c68f skills/review- 57d0f2511e950edf8b390a2b5c44cd4532a6aa258d78e8bffc7167a6449dc054 skills/write-specs-readmodels/SKILL.md e6bc79cd003e97c591dc0c12c7aa727b809f0e7a8ac9e5d05ad7ab6d79dc8c0e skills/write-specs/SKILL.md 6dc9b60a7a088c2a9860f4518c5256076b3b3256dd763b237aac05558787b03a skills/write-specs/references/EXAMPLES.md -406146ead65d1a4530a8c7d321192d2d3b2e37bb37a78113a9149f33b8410506 submissions/cursor.json -0a6a79f150e7441a97e716fb153636cb6b9140d830a440faabbdb84cf180ee81 submissions/openai.json +0d50384ee27cb301a0af6e648b46046de9f8774bd7ae49b414910a46367cd711 submissions/cursor.json +e6a860edace4c93a013da26e06d87040743de6285ecb636418f5d783d656d7b6 submissions/openai.json diff --git a/assets/cratis-logo.png b/assets/cratis-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..585c56ed687a116e9d8bab66cd3fa6a13ab42ae6 GIT binary patch literal 8035 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 { See [dialogs.md](../../rules/dialogs.md) and the `stepper-command-dialog` skill for the full dialog patterns. +#### Confirming, and showing that something is in progress + +Do not build either of these into a page. `ConfirmationDialog` and `BusyIndicatorDialog` are +registered once at the app root through `DialogComponents` and raised by hook from anywhere, which is +what keeps every confirmation and every busy indicator looking the same: + +```tsx +import { DialogButtons, DialogResult, useConfirmationDialog, useBusyIndicator } from '@cratis/arc.react/dialogs'; + +const [confirm] = useConfirmationDialog(); +if (await confirm('Delete this account?', `"${account.name}" disappears permanently.`, DialogButtons.YesNo) !== DialogResult.Yes) return; +``` + +**A busy indicator dialog is only for work that genuinely has to block the user.** It is modal and +deliberately non-dismissible, so it takes the whole screen away until the work finishes — reach for it +when carrying on would be wrong: a multi-step import, a migration, something the next click would +corrupt or duplicate. + +For everything else — and that is most of it — the in-flight button is the right control. A command +that appends events and returns in milliseconds sits behind a button that already disables itself and +shows progress (eventual-consistency rule 9); putting a modal in front of it makes the screen flash +and tells the user nothing. Never open one just to signal "working". + +When you do use it, pair it with `closeBusy()` in a `finally` — a non-dismissible dialog whose close +was skipped strands the user with no way out: + +```tsx +const [showBusy, closeBusy] = useBusyIndicator('Importing', 'This takes a moment.'); +showBusy(); +try { await importEverything(); } finally { closeBusy(); } +``` + --- ### Step 4 — Row selection and edit dialog diff --git a/plugins/public-cratis-ai/skills/event-type-migrations/SKILL.md b/plugins/public-cratis-ai/skills/event-type-migrations/SKILL.md index 9effec3..da6df2d 100644 --- a/plugins/public-cratis-ai/skills/event-type-migrations/SKILL.md +++ b/plugins/public-cratis-ai/skills/event-type-migrations/SKILL.md @@ -29,13 +29,18 @@ Generation 1 (stored) → Migration 1→2 → Migration 2→3 → Current (Gener ### 1. Keep the prior record and bump the generation on the new one -Keep the old shape available to the migration as `TPrevious`, and mark the current record's generation: +Keep the old shape available to the migration as `TPrevious`. Mark the current record's generation with `[EventType(generation: N)]` as always, and mark the prior record with **`[EventTypeGenerationFor(N-1)]`** instead of its own `[EventType]` — its event type id is then resolved from the current record's `[EventType]`, so the two can never end up with mismatched ids: ```csharp [EventType(generation: 2)] public record OrderPlaced(OrderId OrderId, Currency Currency); // generation 2 (current) + +[EventTypeGenerationFor(1)] +public record OrderPlacedV1(OrderId OrderId); // generation 1 (prior) ``` +> **Older style, still supported:** you can instead give `OrderPlacedV1` its own `[EventType("order-placed", generation: 1)]`, as long as the id string is explicit and **identical** to the id on `OrderPlaced`. This is not deprecated, but prefer `[EventTypeGenerationFor]` for anything new — an omitted or mismatched id on this older style silently defaults to the CLR type name, which Chronicle then treats as a wholly unrelated event type, and the migration never applies. Two analyzers (`CHR0037`, `CHR0049`) and a constructor-time exception (`MigrationGenerationsMustShareEventTypeId`) catch this mistake for both styles. + ### 2. Write the migration Implement `EventTypeMigration` — `TUpgrade` is the current shape, `TPrevious` the prior. Chronicle extracts the generations, validates they're consecutive, and discovers the migration automatically (no registration). @@ -55,6 +60,21 @@ public class OrderPlacedV1ToV2 : EventTypeMigration The property builder exposes `DefaultValue`, `RenamedFrom`, `Split`, and `Combine` — use them to express the change declaratively. Both `Upcast` and `Downcast` are abstract on the base, so both must be implemented (`Downcast` may be a no-op `builder.Properties(_ => { })` when no consumer needs the gen-1 shape). +### 2b. When the *values* changed meaning, declare a value map + +The operations above move values between properties. When a value itself means something different in the new generation — an enum renumbered, a status code set replaced — override **`MapValues`** on the migration instead. It is declared once and applied forward when upcasting and inverted when downcasting: + +```csharp +public override void MapValues(IEventValueMapBuilder builder) => + builder.For(current => current.Status, previous => previous.Status, map => map + .Map(OrderStatusV1.Pending, OrderStatus.Awaiting) + .Map(OrderStatusV1.Done, OrderStatus.Completed)); +``` + +Values the map doesn't mention are carried across unchanged. Two values collapsing onto one take the first pair declared for that value on the way back. `MapValues` runs *before* `Upcast`/`Downcast`, so a direction that states its own transformation for the property keeps it — that's also how you express a deliberately one-way translation (`builder.Properties(pb => pb.MapValues(...))`). + +> **An enum gaining a member or having a member renamed needs no migration at all** — Chronicle accepts both in place and updates the registered schema, because neither changes what an already stored value means. Only a *removed* or *renumbered* member needs a new generation plus a value map. + ### 3. Chain across generations For three generations, write two migrations (`1→2`, `2→3`) — each only knows its adjacent pair; Chronicle chains them. @@ -64,6 +84,7 @@ For three generations, write two migrations (`1→2`, `2→3`) — each only kno | Pitfall | Why it breaks | |---|---| | Editing the stored event record without bumping `generation` | Old events still carry the old schema; Chronicle won't migrate them | +| Giving the prior record its own `[EventType]` with no id, or an id that doesn't exactly match the current generation's | Chronicle treats the two as unrelated event types and the migration never applies; use `[EventTypeGenerationFor]` so there's no id to mismatch | | Adding a nullable value type to handle "missing old data" | Analyzer-flagged anti-pattern; use a migration default | | A migration that throws on a null/missing old field | Old events may lack fields entirely — null-coalesce / default | | Splitting one event into two inside `Upcast` | `Upcast` returns one event; model a split as a reactor/command, not a schema migration | diff --git a/provenance.json b/provenance.json index 8b28106..b9aed22 100644 --- a/provenance.json +++ b/provenance.json @@ -3,9 +3,9 @@ "state": "PUBLIC_EVALUATION_MARKETPLACE_NOT_SUPPORT", "canonicalRepository": "Cratis/AI", "distributionRepository": "Cratis/AI.Distribution", - "sourceCommit": "ba87a907cf45f11cb804d0a9063cb3709cce1b16", + "sourceCommit": "4d45c9a82e47f0bdb323055a920a7ce8fe2b4def", "generator": "tooling/generate-public-marketplace-distribution.mjs", - "version": "0.2.0", + "version": "0.2.1", "profileId": "public-cratis-ai", "selectedHarnesses": [ "agent-skills", @@ -69,6 +69,21 @@ } ], "repositoryOnlySkillExclusions": [], + "brandAsset": { + "sourceRepository": "https://github.com/Cratis/Documentation", + "sourceRevision": "a5a53c2cba1f3cbe5c29c5ec70fb3d533ac0694c", + "sourcePath": "web/public/favicon-512.png", + "sha256": "da99d76b1513c92617e4f3104437fe8988a3b94cc27d457955eb7e155403b7f6", + "copies": [ + "assets/cratis-logo.png", + "plugins/public-cratis-ai/assets/cratis-logo.png" + ] + }, + "openAiInterface": { + "developerName": "SINDRE ALSTAD WILTING", + "composerIcon": "./assets/cratis-logo.png", + "logo": "./assets/cratis-logo.png" + }, "nativeComponentsIncluded": false, "nativeComponentsReason": "Native rules and instructions retain separate semantic artifacts and are not repackaged as skills.", "canonicalFiles": [ @@ -254,8 +269,8 @@ }, { "path": "skills/cratis-react-page/SKILL.md", - "size": 8833, - "sha256": "7dfe2eb8a8336f5b3f65af79105d07427b55cc651fac93fa979f42a6878b7f08", + "size": 10568, + "sha256": "e623dacbc6a3114236b70257046ac8445a4432c8fa7be16ac07bd7b59e3b165b", "copies": [ "skills/cratis-react-page/SKILL.md", "plugins/public-cratis-ai/skills/cratis-react-page/SKILL.md" @@ -470,8 +485,8 @@ }, { "path": "skills/event-type-migrations/SKILL.md", - "size": 4357, - "sha256": "eec56904897163d9261d3ec976595956fa089a717c7854837ef318e75e387412", + "size": 7041, + "sha256": "459d68ef45d14b647d7523acf8177f698e798555b62eb1ae79d31cd50f1379cc", "copies": [ "skills/event-type-migrations/SKILL.md", "plugins/public-cratis-ai/skills/event-type-migrations/SKILL.md" diff --git a/skills/cratis-react-page/SKILL.md b/skills/cratis-react-page/SKILL.md index 6c6c44e..241ed6f 100644 --- a/skills/cratis-react-page/SKILL.md +++ b/skills/cratis-react-page/SKILL.md @@ -1,6 +1,6 @@ --- name: cratis-react-page -description: Step-by-step guidance for building a React page in a Cratis Arc application — DataPage lists, CommandDialog toolbar actions, row selection, details components, observable queries, and MVVM. Use when building or modifying a page that lists/displays data, adding a table, wiring Add/Edit/Delete, or connecting a component to a proxy-generated query (standard or observable). +description: Step-by-step guidance for building a React page in a Cratis Arc application — DataPage lists, CommandDialog toolbar actions, confirmation and busy-indicator dialogs, row selection, details components, observable queries, and MVVM. Use when building or modifying a page that lists/displays data, adding a table, wiring Add/Edit/Delete, connecting a component to a proxy-generated query (standard or observable), or asking the user to confirm something. --- ## Workflow @@ -93,6 +93,38 @@ export const AccountsPage = () => { See [dialogs.md](../../rules/dialogs.md) and the `stepper-command-dialog` skill for the full dialog patterns. +#### Confirming, and showing that something is in progress + +Do not build either of these into a page. `ConfirmationDialog` and `BusyIndicatorDialog` are +registered once at the app root through `DialogComponents` and raised by hook from anywhere, which is +what keeps every confirmation and every busy indicator looking the same: + +```tsx +import { DialogButtons, DialogResult, useConfirmationDialog, useBusyIndicator } from '@cratis/arc.react/dialogs'; + +const [confirm] = useConfirmationDialog(); +if (await confirm('Delete this account?', `"${account.name}" disappears permanently.`, DialogButtons.YesNo) !== DialogResult.Yes) return; +``` + +**A busy indicator dialog is only for work that genuinely has to block the user.** It is modal and +deliberately non-dismissible, so it takes the whole screen away until the work finishes — reach for it +when carrying on would be wrong: a multi-step import, a migration, something the next click would +corrupt or duplicate. + +For everything else — and that is most of it — the in-flight button is the right control. A command +that appends events and returns in milliseconds sits behind a button that already disables itself and +shows progress (eventual-consistency rule 9); putting a modal in front of it makes the screen flash +and tells the user nothing. Never open one just to signal "working". + +When you do use it, pair it with `closeBusy()` in a `finally` — a non-dismissible dialog whose close +was skipped strands the user with no way out: + +```tsx +const [showBusy, closeBusy] = useBusyIndicator('Importing', 'This takes a moment.'); +showBusy(); +try { await importEverything(); } finally { closeBusy(); } +``` + --- ### Step 4 — Row selection and edit dialog diff --git a/skills/event-type-migrations/SKILL.md b/skills/event-type-migrations/SKILL.md index 9effec3..da6df2d 100644 --- a/skills/event-type-migrations/SKILL.md +++ b/skills/event-type-migrations/SKILL.md @@ -29,13 +29,18 @@ Generation 1 (stored) → Migration 1→2 → Migration 2→3 → Current (Gener ### 1. Keep the prior record and bump the generation on the new one -Keep the old shape available to the migration as `TPrevious`, and mark the current record's generation: +Keep the old shape available to the migration as `TPrevious`. Mark the current record's generation with `[EventType(generation: N)]` as always, and mark the prior record with **`[EventTypeGenerationFor(N-1)]`** instead of its own `[EventType]` — its event type id is then resolved from the current record's `[EventType]`, so the two can never end up with mismatched ids: ```csharp [EventType(generation: 2)] public record OrderPlaced(OrderId OrderId, Currency Currency); // generation 2 (current) + +[EventTypeGenerationFor(1)] +public record OrderPlacedV1(OrderId OrderId); // generation 1 (prior) ``` +> **Older style, still supported:** you can instead give `OrderPlacedV1` its own `[EventType("order-placed", generation: 1)]`, as long as the id string is explicit and **identical** to the id on `OrderPlaced`. This is not deprecated, but prefer `[EventTypeGenerationFor]` for anything new — an omitted or mismatched id on this older style silently defaults to the CLR type name, which Chronicle then treats as a wholly unrelated event type, and the migration never applies. Two analyzers (`CHR0037`, `CHR0049`) and a constructor-time exception (`MigrationGenerationsMustShareEventTypeId`) catch this mistake for both styles. + ### 2. Write the migration Implement `EventTypeMigration` — `TUpgrade` is the current shape, `TPrevious` the prior. Chronicle extracts the generations, validates they're consecutive, and discovers the migration automatically (no registration). @@ -55,6 +60,21 @@ public class OrderPlacedV1ToV2 : EventTypeMigration The property builder exposes `DefaultValue`, `RenamedFrom`, `Split`, and `Combine` — use them to express the change declaratively. Both `Upcast` and `Downcast` are abstract on the base, so both must be implemented (`Downcast` may be a no-op `builder.Properties(_ => { })` when no consumer needs the gen-1 shape). +### 2b. When the *values* changed meaning, declare a value map + +The operations above move values between properties. When a value itself means something different in the new generation — an enum renumbered, a status code set replaced — override **`MapValues`** on the migration instead. It is declared once and applied forward when upcasting and inverted when downcasting: + +```csharp +public override void MapValues(IEventValueMapBuilder builder) => + builder.For(current => current.Status, previous => previous.Status, map => map + .Map(OrderStatusV1.Pending, OrderStatus.Awaiting) + .Map(OrderStatusV1.Done, OrderStatus.Completed)); +``` + +Values the map doesn't mention are carried across unchanged. Two values collapsing onto one take the first pair declared for that value on the way back. `MapValues` runs *before* `Upcast`/`Downcast`, so a direction that states its own transformation for the property keeps it — that's also how you express a deliberately one-way translation (`builder.Properties(pb => pb.MapValues(...))`). + +> **An enum gaining a member or having a member renamed needs no migration at all** — Chronicle accepts both in place and updates the registered schema, because neither changes what an already stored value means. Only a *removed* or *renumbered* member needs a new generation plus a value map. + ### 3. Chain across generations For three generations, write two migrations (`1→2`, `2→3`) — each only knows its adjacent pair; Chronicle chains them. @@ -64,6 +84,7 @@ For three generations, write two migrations (`1→2`, `2→3`) — each only kno | Pitfall | Why it breaks | |---|---| | Editing the stored event record without bumping `generation` | Old events still carry the old schema; Chronicle won't migrate them | +| Giving the prior record its own `[EventType]` with no id, or an id that doesn't exactly match the current generation's | Chronicle treats the two as unrelated event types and the migration never applies; use `[EventTypeGenerationFor]` so there's no id to mismatch | | Adding a nullable value type to handle "missing old data" | Analyzer-flagged anti-pattern; use a migration default | | A migration that throws on a null/missing old field | Old events may lack fields entirely — null-coalesce / default | | Splitting one event into two inside `Upcast` | `Upcast` returns one event; model a split as a reactor/command, not a schema migration | diff --git a/submissions/cursor.json b/submissions/cursor.json index 37b0c48..314ab0a 100644 --- a/submissions/cursor.json +++ b/submissions/cursor.json @@ -6,7 +6,7 @@ "pluginManifest": "plugin.json", "marketplaceManifest": ".cursor-plugin/marketplace.json", "category": "Developer Tools", - "version": "0.2.0", + "version": "0.2.1", "description": "Cratis AI skills for event-sourced and CQRS application development", "supportUrl": "https://github.com/Cratis/AI/issues", "localValidationRequired": true, diff --git a/submissions/openai.json b/submissions/openai.json index 00f2962..5d9d81a 100644 --- a/submissions/openai.json +++ b/submissions/openai.json @@ -9,12 +9,13 @@ "website": "https://cratis.io/ai", "supportUrl": "https://github.com/Cratis/AI/issues", "sourceRepository": "https://github.com/Cratis/AI.Distribution", - "version": "0.2.0", + "version": "0.2.1", "releaseNotes": "Initial unsupported 0.x public evaluation release.", - "portalReadiness": "OWNER_IDENTITY_AND_LISTING_ASSETS_REQUIRED", + "portalReadiness": "OWNER_IDENTITY_AND_LEGAL_METADATA_REQUIRED", + "developerName": "SINDRE ALSTAD WILTING", + "logo": "plugins/public-cratis-ai/assets/cratis-logo.png", "requiredOwnerInputs": [ "verified OpenAI developer identity", - "logo", "privacy policy URL", "terms URL", "country availability",