Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion handbooks/Vendor_Extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).

Expand Down
Loading