From 6e16308b36e3a368bc09ed17c2dbb2c78a5384d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Labont=C3=A9?= Date: Tue, 13 Oct 2026 08:45:54 -0400 Subject: [PATCH] docs: cite clabonte/generator#2639 for the filtered-group event classes (was "not filed") Co-Authored-By: Claude Opus 5.5 --- compatibility.md | 8 ++++---- handbooks/Vendor_Extensions.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compatibility.md b/compatibility.md index 716116b..82e4010 100644 --- a/compatibility.md +++ b/compatibility.md @@ -1219,7 +1219,7 @@ The kit keeps both at `error`. The kit's grammar is the authoritative one (the j - **Item 7 closed:** the cross-pillar failures project-level `validate` alone reported are gone, and the one that remains (the reverse edge) is spec-level. - **Item 8, new: `snapshot` in a pillar-bound C# group emits other pillars' snapshots**, at `0.15.0` and `0.14.0` alike. `SnapshotArtifact` is `GLOBAL` and loads every `*Snapshot.yaml` with no domain filter, so the holder's group fails `CS0246` in `CustomerSnapshot.g.cs` / `TenantSnapshot.g.cs` and the owner's in `OrderSnapshot.g.cs`. Nothing in the spec avoids it. Filed as `clabonte/generator#2568` (§49); **closed at `0.16.0`**. Separately, a pillar-bound `event` emitted no `*Event` classes in the repro while `service` referenced them; that may be the repro's bundled AsyncAPI and is not documented. -**Status at `0.16.0`:** item 8 is closed by `clabonte/generator#2568`: a pillar-bound group's `snapshot` and `snapshotContext` emit only owned entities, and no snapshot file fails to compile. Item 5 is unchanged: `validate` is clean at both levels, and `generate` throws `OperationResolutionException` in both groups. Items 1–4, 6 and 7 re-measured as at `0.15.0`. The tenancy-column trap is now `TENANT_REMOTE_REFERENCE_FOREIGN_KEY_MISMATCH` (`#2569`). **Item 9, new, open, not filed:** any domain-filtered C# group (`pillar` or `domains.include`) with `event` emits no `{Message}Event` classes while `service` references them (`CS0246`), at `0.16.0` and `0.15.0`. The unfiltered control builds clean, which settles item 8's aside: the repro's AsyncAPI is not the cause. Re-measured on a split holding `Customer` only, with `Tenant` reached through `resolve: remote`. +**Status at `0.16.0`:** item 8 is closed by `clabonte/generator#2568`: a pillar-bound group's `snapshot` and `snapshotContext` emit only owned entities, and no snapshot file fails to compile. Item 5 is unchanged: `validate` is clean at both levels, and `generate` throws `OperationResolutionException` in both groups. Items 1–4, 6 and 7 re-measured as at `0.15.0`. The tenancy-column trap is now `TENANT_REMOTE_REFERENCE_FOREIGN_KEY_MISMATCH` (`#2569`). **Item 9, new, open, filed as `clabonte/generator#2639`:** any domain-filtered C# group (`pillar` or `domains.include`) with `event` emits no `{Message}Event` classes while `service` references them (`CS0246`), at `0.16.0` and `0.15.0`. The unfiltered control builds clean, which settles item 8's aside: the repro's AsyncAPI is not the cause. Re-measured on a split holding `Customer` only, with `Tenant` reached through `resolve: remote`. **What generates on both sides at `0.15.0`:** every form in §14.10 except a cross-pillar reverse edge and a child route nested under another pillar's parent. **Tenancy** has two working forms, `belongsTo` with a hold and `resolve: remote`; the latter must sit on the column named by `tenancy.tenant.foreignKey` (`clabonte/generator#2569`, §49). The Spectral follow-up below is done: `specfuse-x-references-shape` accepts and checks the object form. @@ -1427,10 +1427,10 @@ The C# server prefixes every route with the path part of the server URL; the cli - **`specfuse-no-inline-enums` gains a second `given`** for an inline enum inside an `allOf`/`oneOf`/`anyOf` member (`#2579`). Through `0.15.0` that form passed `validate` and failed `generate` with `PROPERTY_INNER_ENUM`. Fixture `inline-enum-wrapped.yaml`: a bare enum and a wrapped one must fire; a wrapped `$ref` must not. - **No rule** for the other new findings: each needs the project file or spans two documents. `ENTITY_MISSING_ID` is already covered more strictly by `specfuse-main-resource-has-id`. -**Found while measuring, not filed:** +**Found while measuring:** -1. **`Error.code` (corrects §51 item 2).** The C# `domainExceptions` templates set `Error.Code` to an integer, the HTTP status or an `int errorCode`, and set `Error.Id` to a string. The kit's `Error` types `code` as a snake_case string and `id` as `format: uuid`, so a project that registers `domainExceptions` fails `CS0029` on 22 assignments, measured on a `hello-orders` copy. `hello-orders` does not register the artifact. The consumer's integer `code` plus a string `reason` is the shape that compiles. `API_Handbook.md` §2.1 now says so. **Open decision:** does the kit's `Error` move to an integer `code`, a string `id` and a `reason` field, or does the generator move to a string `code`? Same shape as the `#2371` decision. -2. **§44 item 9.** A domain-filtered C# group (`pillar` or `domains.include`) with `event` and `service` emits no `{Message}Event` classes, while the service constructs them: `CS0246`, at `0.16.0` and `0.15.0`. The unfiltered control builds clean. +1. **`Error.code` (corrects §51 item 2).** The C# `domainExceptions` templates set `Error.Code` to an integer, the HTTP status or an `int errorCode`, and set `Error.Id` to a string. The kit's `Error` types `code` as a snake_case string and `id` as `format: uuid`, so a project that registers `domainExceptions` fails `CS0029` on 22 assignments, measured on a `hello-orders` copy. `hello-orders` does not register the artifact. The consumer's integer `code` plus a string `reason` is the shape that compiles. `API_Handbook.md` §2.1 now says so. **Open decision:** does the kit's `Error` move to an integer `code`, a string `id` and a `reason` field, or does the generator move to a string `code`? Same shape as the `#2371` decision. Not filed: it waits on that decision. +2. **§44 item 9.** A domain-filtered C# group (`pillar` or `domains.include`) with `event` and `service` emits no `{Message}Event` classes, while the service constructs them: `CS0246`, at `0.16.0` and `0.15.0`. The unfiltered control builds clean. Filed as `clabonte/generator#2639` (2026-10-13). ## Outstanding kit-side work diff --git a/handbooks/Vendor_Extensions.md b/handbooks/Vendor_Extensions.md index 7558051..e82649f 100644 --- a/handbooks/Vendor_Extensions.md +++ b/handbooks/Vendor_Extensions.md @@ -4568,7 +4568,7 @@ What follows from the table: - **The tenancy root has two working forms.** `belongsTo` to the tenant with a hold generates on both sides (second row), and the child carries the `I{Tenant}Scoped` marker. A `resolve: remote` reference to the tenant carries the marker with no `belongsTo` and no hold (§14.11). Measured with a `tenancy` block: under `belongsTo` and under `resolve: remote`, `Order` implemented the tenant marker. Under `x-references: Tenant` and under `x-references: none`, it did not. The generated `Order` events carried the marker in all four cases. - **The C# Domain no longer maps `Read{Entity}`** (`clabonte/generator#2392`). At `0.15.0` the generated C# maps through Mapperly, and no group emits an `AutoMapperProfile.g.cs`. In the measured groups, no generated file names a `Read{Entity}` except the replica's own entity and configuration and the holder's entity whose FK binds to it. Dart and TypeScript `dto` groups no longer emit a `Read{Entity}` client type. Checked with `dotnet build` on an unbound C# group of the held spec, with the domain artifacts it needs to compile (`domainValidation`, `domainExceptions`, `serviceInterface`, `service`, `repositoryInterface`, `event`, `eventRuntime`, `tenancyMarker`, `snapshot`, and a `tenancy` block). At `0.15.0` it built with 0 errors. At `0.14.0` it failed with `CS0246` on `ReadTenant`, `ReadOrder` and `ReadCustomer` in `AutoMapperProfile.g.cs`. - **`snapshot` follows the pillar from generator `0.16.0`** (`clabonte/generator#2568`). A pillar-bound group emits only the `{Entity}Snapshot` and `{Entity}SnapshotChanges` of the entities it owns: `core` gets `CustomerSnapshot`, `sales` gets `OrderSnapshot` and `OrderLineSnapshot`. At `0.15.0` and `0.14.0` every group emitted every snapshot, and each foreign one failed `CS0246` on the entity it maps from. An unbound group emits exactly what it did before. -- **A pillar-bound C# group with `event` and `service` still does not compile, at `0.16.0` or `0.15.0`.** `event` emits the event infrastructure but no `{Message}Event` class, while `Default{Entity}Service` constructs them, so the build fails with `CS0246` on `OrderCreatedEvent`, `CustomerUpdatedEvent` and the rest. The same happens under `groups[].domains`. The same artifacts in an unfiltered group emit every event class and build with 0 errors. Nothing in the spec avoids it (`compatibility.md` §44 item 9). +- **A pillar-bound C# group with `event` and `service` still does not compile, at `0.16.0` or `0.15.0`.** `event` emits the event infrastructure but no `{Message}Event` class, while `Default{Entity}Service` constructs them, so the build fails with `CS0246` on `OrderCreatedEvent`, `CustomerUpdatedEvent` and the rest. The same happens under `groups[].domains`. The same artifacts in an unfiltered group emit every event class and build with 0 errors. Nothing in the spec avoids it (`clabonte/generator#2639`; `compatibility.md` §44 item 9). These verdicts are tied to `0.16.0`; re-measure them at every pin bump (`compatibility.md` §44).