Skip to content

Commit 0f1c8d8

Browse files
committed
Merge Phase V — docs cross-referenced to conformance fixtures
Each of the 8 feature docs gained a ## Verified by section listing the conformance fixtures that gate the documented behavior. NEW docs/CONFORMANCE.md is the inverse index: per-corpus totals, per-port pass status, fixture-to-doc mapping. docs/README.md links to it. 138 fixtures cross-referenced across 5 active corpora: - conformance/ (metamodel, 85) — grouped under entities/field-types/ source-kinds/relationships/templates/loaders - yaml-conformance/ (6) → yaml-authoring.md - verify-conformance/ (31) → migrations-and-drift.md - render-conformance/ (4) → templates-and-payloads.md - persistence-conformance/ (12) → migrations-and-drift.md + source-kinds.md Zero orphans (no fixture without a feature doc, no feature without gating fixtures). Codegen-conformance noted as deferred (FR-007). The docs are now provably grounded in shipped tests, not aspirational — LLMs reading a feature doc can verify the documented behavior by following the fixture links and reading the expected.json + per-port runner outcomes.
2 parents 05c2396 + c45fa2b commit 0f1c8d8

10 files changed

Lines changed: 363 additions & 0 deletions

docs/CONFORMANCE.md

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Conformance coverage
2+
3+
The MetaObjects standard has 5 cross-language conformance corpora plus a deferred
4+
6th (`codegen-conformance/`, tracked as FR-007). Every port runs every applicable
5+
corpus and asserts the same expected behavior against the same fixtures. **This
6+
page is the inverse index**: fixture → feature doc + per-port pass status.
7+
8+
If you are coming from a feature doc's `## Verified by` section, you are in the
9+
right place. If you are wondering whether a particular fixture has a
10+
human-readable explanation somewhere, look it up in the
11+
"Fixture-to-doc mapping" table below.
12+
13+
## Per-corpus totals
14+
15+
| Corpus | Fixtures | TS | Java | Kotlin | C# | Python |
16+
|---|---|---|---|---|---|---|
17+
| [`fixtures/conformance/`](../fixtures/conformance/) (metamodel) | 85 | 85 / 85 | 85 / 85 | inherits via `metadata-ktx` | source-v2 cluster + `doc-common-attrs-on-all-types` are open gaps | 91 / 91 (also gates loader extensions) |
18+
| [`fixtures/yaml-conformance/`](../fixtures/yaml-conformance/) | 6 | 6 / 6 | 6 / 6 | inherits via Java | 6 / 6 | 6 / 6 |
19+
| [`fixtures/verify-conformance/`](../fixtures/verify-conformance/) | 31 | 31 / 31 | 31 / 31 | inherits via Java | 31 / 31 | 31 / 31 |
20+
| [`fixtures/render-conformance/`](../fixtures/render-conformance/) | 4 | 4 / 4 | 4 / 4 | inherits via Java | 4 / 4 | 4 / 4 |
21+
| [`fixtures/persistence-conformance/`](../fixtures/persistence-conformance/) | 12 (9 query + 3 migration) | 12 / 12 | 12 / 12 | 12 / 12 (via Exposed) | 12 / 12 | 12 / 12 |
22+
| `fixtures/codegen-conformance/` (FR-007 — DROPPED in favor of `persistence-conformance` participation) | 0 | n/a | n/a | n/a | n/a | n/a |
23+
24+
Per-port runners + commands:
25+
26+
| Port | Metamodel + YAML + render + verify | Persistence |
27+
|---|---|---|
28+
| TypeScript | `cd server/typescript && bun test` (per-package, `~3s`) | `scripts/integration-test.sh ts` (needs Docker) |
29+
| Java | `mvn -pl metaobjects-conformance test` (and per-tier `-pl render`, etc.) | `scripts/integration-test.sh java` (needs Docker) |
30+
| Kotlin | `mvn -pl codegen-kotlin test` (snapshot suite) | `mvn -pl integration-tests-kotlin test` (needs Docker) |
31+
| C# | `dotnet test` (per project) | `scripts/integration-test.sh csharp` (needs Docker) |
32+
| Python | `pytest` (per package) | `scripts/integration-test.sh python` (needs Docker) |
33+
34+
The `persistence-conformance` corpus is intentionally **on-demand** — none of the
35+
unit-test runners (`bun test`, `dotnet test`, `pytest`, `mvn test`) pull Docker.
36+
`scripts/integration-test.sh` is the entry point and is wired into
37+
[`docs/RELEASING.md`](RELEASING.md) §2b as the pre-`latest` gate.
38+
39+
## Fixture-to-doc mapping
40+
41+
### `fixtures/conformance/` — metamodel loader + canonical serializer (85)
42+
43+
| Fixture prefix | Feature doc |
44+
|---|---|
45+
| `loader-basic-*`, `error-parse-*` | [features/loaders.md](features/loaders.md) |
46+
| `extends-*`, `error-extends-*` | [features/entities.md](features/entities.md) (inheritance) |
47+
| `identity-*`, `subtype-entity-*`, `subtype-value-*` | [features/entities.md](features/entities.md) (identity / entity vs value) |
48+
| `attr-*`, `error-attr-*`, `error-reserved-word-as-attr` | [features/entities.md](features/entities.md) (attributes) |
49+
| `doc-common-attrs-*` | [features/entities.md](features/entities.md) (documentation common attrs) |
50+
| `auto-set-on-*` | [features/entities.md](features/entities.md) (auto-set timestamps) |
51+
| `attr-filter-*`, `loader-filterable-*`, `warning-filterable-*`, `layout-data-grid-*`, `error-data-grid-*` | [features/entities.md](features/entities.md) (filter / sort / grid) |
52+
| `overlay-*` | [features/entities.md](features/entities.md) (overlay / merge) |
53+
| `field-string-*`, `field-decimal-*`, `field-object-storage-*`, `error-field-object-storage-*` | [features/field-types.md](features/field-types.md) |
54+
| `currency-*` | [features/field-types.md](features/field-types.md) (currency) |
55+
| `enum-*`, `error-enum-*` | [features/field-types.md](features/field-types.md) (enum) |
56+
| `source-rdb-*`, `source-db-table-*`, `source-db-view-*`, `source-multi-source-*`, `error-source-*` | [features/source-kinds.md](features/source-kinds.md) |
57+
| `relationship-*`, `error-unknown-relationship-*` | [features/relationships.md](features/relationships.md) |
58+
| `template-*`, `error-template-*` | [features/templates-and-payloads.md](features/templates-and-payloads.md) |
59+
| `origin-*`, `error-origin-*` | [features/templates-and-payloads.md](features/templates-and-payloads.md) (payload origins) |
60+
| `smoke-empty-metadata` | [features/entities.md](features/entities.md) |
61+
62+
### `fixtures/yaml-conformance/` (6)
63+
64+
All 6 fixtures → [features/yaml-authoring.md](features/yaml-authoring.md).
65+
66+
### `fixtures/render-conformance/` (4)
67+
68+
All 4 fixtures → [features/templates-and-payloads.md](features/templates-and-payloads.md)
69+
(render engine output section).
70+
71+
### `fixtures/verify-conformance/` (31)
72+
73+
All 31 fixtures → [features/migrations-and-drift.md](features/migrations-and-drift.md)
74+
(template drift section — `Renderer.verify`).
75+
76+
### `fixtures/persistence-conformance/` (12)
77+
78+
- `migrations/*` (3) → [features/migrations-and-drift.md](features/migrations-and-drift.md) (schema migration section)
79+
- `queries/*` (9) → [features/source-kinds.md](features/source-kinds.md) (query semantics against `source.rdb`)
80+
81+
## Orphaned fixtures (tested but not yet documented)
82+
83+
All 138 fixtures across the 5 active corpora map to a feature doc. None are
84+
orphaned today.
85+
86+
If you add a new fixture and don't see a clear home for it, either:
87+
88+
1. Add a section to the closest matching feature doc and reference it from its
89+
`## Verified by` block, or
90+
2. Open an issue if the fixture exercises behavior the feature docs haven't yet
91+
described.
92+
93+
## Orphaned docs (documented but no fixture coverage)
94+
95+
None of the 8 feature docs lack fixture coverage. The closest case is the
96+
high-level overview material in each doc (e.g., the "Anatomy of an entity"
97+
explainer in `entities.md`) — these are pedagogical, not behavioral, and don't
98+
require pinning.
99+
100+
## See also
101+
102+
- [features/](features/) — the per-feature reference, each with its own `## Verified by`
103+
- [`spec/conformance-tests.md`](../spec/conformance-tests.md) — fixture format + canonical serializer contract
104+
- [`spec/cross-language-porting-guide.md`](../spec/cross-language-porting-guide.md) — how a new port wires up against the corpora
105+
- [`fixtures/conformance/ERROR-CODES.json`](../fixtures/conformance/ERROR-CODES.json) — the enumerated error codes every `error-*` fixture pins
106+
- [`docs/RELEASING.md`](RELEASING.md)`scripts/integration-test.sh` runs `persistence-conformance` per port pre-release

docs/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ copy-paste cross-port without context-switching.
1515
```
1616
docs/
1717
├── README.md # this file
18+
├── CONFORMANCE.md # inverse index: fixture → feature doc + per-port pass status
1819
├── features/ # one file per metamodel feature
1920
│ ├── entities.md
2021
│ ├── source-kinds.md
@@ -42,6 +43,7 @@ docs/
4243
| Author metadata in YAML instead of JSON | [`features/yaml-authoring.md`](features/yaml-authoring.md) |
4344
| Wire prompt construction (FR-004) | [`features/templates-and-payloads.md`](features/templates-and-payloads.md) |
4445
| Know which feature is supported in which port today | the capability matrix in the root [`README.md`](../README.md) or the per-port "Capability snapshot" table |
46+
| See which conformance fixtures gate each feature (and which port passes which) | [`CONFORMANCE.md`](CONFORMANCE.md) |
4547
| Read the canonical spec (target-agnostic) | [`../spec/`](../spec/) |
4648
| Find a release recipe (Cloudflare D1, etc.) | [`recipes/`](recipes/) |
4749
| See the deeper design rationale for a feature | [`superpowers/specs/`](superpowers/specs/) |

docs/features/entities.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,76 @@ class Author:
236236
bio: Optional[str] = None
237237
```
238238

239+
## Verified by
240+
241+
The following conformance fixtures gate this feature's behavior across ports:
242+
243+
**Basic entity loading**
244+
245+
- [`fixtures/conformance/smoke-empty-metadata/`](../../fixtures/conformance/smoke-empty-metadata/) — empty metadata loads without error
246+
- [`fixtures/conformance/loader-basic-single-entity/`](../../fixtures/conformance/loader-basic-single-entity/) — single `object.entity` round-trip
247+
- [`fixtures/conformance/subtype-entity-with-identity/`](../../fixtures/conformance/subtype-entity-with-identity/) — `object.entity` accepts `identity.primary`
248+
- [`fixtures/conformance/subtype-entity-missing-primary-warning/`](../../fixtures/conformance/subtype-entity-missing-primary-warning/) — warning when an entity has no primary identity
249+
- [`fixtures/conformance/subtype-value-without-identity/`](../../fixtures/conformance/subtype-value-without-identity/) — `object.value` does NOT require identity
250+
251+
**Inheritance via `extends:`**
252+
253+
- [`fixtures/conformance/extends-single-level/`](../../fixtures/conformance/extends-single-level/) — basic `extends` resolution
254+
- [`fixtures/conformance/extends-multi-level/`](../../fixtures/conformance/extends-multi-level/) — multi-hop ancestor chain
255+
- [`fixtures/conformance/extends-abstract-base/`](../../fixtures/conformance/extends-abstract-base/) — `abstract: true` parents are not instantiable
256+
- [`fixtures/conformance/extends-cross-file/`](../../fixtures/conformance/extends-cross-file/) — deferred resolution across files
257+
- [`fixtures/conformance/error-extends-nonexistent/`](../../fixtures/conformance/error-extends-nonexistent/) — `ERR_UNKNOWN_EXTENDS` when parent missing
258+
259+
**Identity**
260+
261+
- [`fixtures/conformance/identity-primary-and-secondary/`](../../fixtures/conformance/identity-primary-and-secondary/) — multiple identities on one entity
262+
- [`fixtures/conformance/identity-reference-simple/`](../../fixtures/conformance/identity-reference-simple/) — FK via `identity.reference`
263+
264+
**Attributes (`@`-prefixed)**
265+
266+
- [`fixtures/conformance/attr-properties-basic/`](../../fixtures/conformance/attr-properties-basic/) — typed attr parsing
267+
- [`fixtures/conformance/attr-default-polymorphic/`](../../fixtures/conformance/attr-default-polymorphic/) — `@default` adopts the field's value type
268+
- [`fixtures/conformance/error-attr-missing-required/`](../../fixtures/conformance/error-attr-missing-required/) — `ERR_MISSING_REQUIRED_ATTR`
269+
- [`fixtures/conformance/error-attr-wrong-type/`](../../fixtures/conformance/error-attr-wrong-type/) — `ERR_BAD_ATTR_VALUE` on type mismatch
270+
- [`fixtures/conformance/error-attr-bad-allowed-value/`](../../fixtures/conformance/error-attr-bad-allowed-value/) — out-of-enumeration attr value rejected
271+
- [`fixtures/conformance/error-reserved-word-as-attr/`](../../fixtures/conformance/error-reserved-word-as-attr/) — `ERR_RESERVED_ATTR` on `@`-prefixing a reserved word
272+
273+
**Documentation common attrs (`description`, `notes`, `title`, …)**
274+
275+
- [`fixtures/conformance/doc-common-attrs-basic/`](../../fixtures/conformance/doc-common-attrs-basic/) — single-line description
276+
- [`fixtures/conformance/doc-common-attrs-multiline/`](../../fixtures/conformance/doc-common-attrs-multiline/) — multi-line description preserved
277+
- [`fixtures/conformance/doc-common-attrs-on-all-types/`](../../fixtures/conformance/doc-common-attrs-on-all-types/) — common attrs accepted on every node kind
278+
- [`fixtures/conformance/doc-common-attrs-stringarray-shapes/`](../../fixtures/conformance/doc-common-attrs-stringarray-shapes/) — `seeAlso` / `aliases` array shapes
279+
280+
**Auto-set timestamps**
281+
282+
- [`fixtures/conformance/auto-set-on-create/`](../../fixtures/conformance/auto-set-on-create/) — `@autoSetOnCreate` honored
283+
- [`fixtures/conformance/auto-set-on-update/`](../../fixtures/conformance/auto-set-on-update/) — `@autoSetOnUpdate` honored
284+
- [`fixtures/conformance/auto-set-on-create-and-update/`](../../fixtures/conformance/auto-set-on-create-and-update/) — both flags coexist
285+
286+
**Filter / sort / data-grid layout**
287+
288+
- [`fixtures/conformance/attr-filter-shorthand/`](../../fixtures/conformance/attr-filter-shorthand/) — `@filterable: true` shorthand
289+
- [`fixtures/conformance/attr-filter-explicit-ops/`](../../fixtures/conformance/attr-filter-explicit-ops/) — explicit op-list form
290+
- [`fixtures/conformance/error-attr-filter-bad-field/`](../../fixtures/conformance/error-attr-filter-bad-field/) — `@filterable` on a non-field rejected
291+
- [`fixtures/conformance/error-attr-filter-bad-op/`](../../fixtures/conformance/error-attr-filter-bad-op/) — unknown operator rejected
292+
- [`fixtures/conformance/error-attr-filter-legacy-string/`](../../fixtures/conformance/error-attr-filter-legacy-string/) — legacy string form rejected
293+
- [`fixtures/conformance/loader-filterable-on-indexed-no-warning/`](../../fixtures/conformance/loader-filterable-on-indexed-no-warning/) — indexed field + `@filterable` is silent
294+
- [`fixtures/conformance/warning-filterable-no-index/`](../../fixtures/conformance/warning-filterable-no-index/) — `@filterable` without an index emits a warning
295+
- [`fixtures/conformance/layout-data-grid-basic/`](../../fixtures/conformance/layout-data-grid-basic/) — `layout.dataGrid` columns + sort
296+
- [`fixtures/conformance/layout-data-grid-multiple-named/`](../../fixtures/conformance/layout-data-grid-multiple-named/) — multiple named grids per entity
297+
- [`fixtures/conformance/error-data-grid-bad-sort-field/`](../../fixtures/conformance/error-data-grid-bad-sort-field/) — `@defaultSortField` must be a real field
298+
299+
**Overlay / merge**
300+
301+
- [`fixtures/conformance/overlay-same-object-different-files/`](../../fixtures/conformance/overlay-same-object-different-files/) — same `package` + `name` merge across files
302+
- [`fixtures/conformance/overlay-attr-last-writer-wins/`](../../fixtures/conformance/overlay-attr-last-writer-wins/) — attr conflict resolution
303+
- [`fixtures/conformance/overlay-merge-flag-explicit/`](../../fixtures/conformance/overlay-merge-flag-explicit/) — `overlay: true` is explicit-merge-intent
304+
305+
Cross-port runner coverage: TS / Java / Kotlin / C# / Python all execute these
306+
via their respective conformance runners. See [`docs/CONFORMANCE.md`](../CONFORMANCE.md)
307+
for the per-port pass/skip ledger.
308+
239309
## See also
240310

241311
- [field-types.md](field-types.md) — all `field.*` subtypes and their per-port mappings

docs/features/field-types.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,44 @@ class Author:
217217
created_at: Optional[datetime] = None
218218
```
219219

220+
## Verified by
221+
222+
The following conformance fixtures gate this feature's behavior across ports:
223+
224+
**Scalar field attributes**
225+
226+
- [`fixtures/conformance/field-string-maxlength/`](../../fixtures/conformance/field-string-maxlength/)`field.string @maxLength`
227+
- [`fixtures/conformance/field-decimal-precision-scale/`](../../fixtures/conformance/field-decimal-precision-scale/)`field.decimal @precision @scale`
228+
229+
**Currency**
230+
231+
- [`fixtures/conformance/currency-default-usd/`](../../fixtures/conformance/currency-default-usd/)`field.currency` defaults `@currency=USD` when omitted
232+
- [`fixtures/conformance/currency-explicit-jpy/`](../../fixtures/conformance/currency-explicit-jpy/) — explicit ISO 4217 honored
233+
- [`fixtures/conformance/currency-precedence-field-vs-view/`](../../fixtures/conformance/currency-precedence-field-vs-view/) — field `@currency` wins over `view.currency` override
234+
235+
**Enum**
236+
237+
- [`fixtures/conformance/enum-inline/`](../../fixtures/conformance/enum-inline/) — inline `field.enum @values`
238+
- [`fixtures/conformance/enum-array/`](../../fixtures/conformance/enum-array/) — array-of-enum field
239+
- [`fixtures/conformance/enum-abstract-extends/`](../../fixtures/conformance/enum-abstract-extends/) — reuse via abstract `field.enum` + `extends`
240+
- [`fixtures/conformance/error-enum-missing-values/`](../../fixtures/conformance/error-enum-missing-values/)`ERR_MISSING_REQUIRED_ATTR` when `@values` absent
241+
- [`fixtures/conformance/error-enum-empty-values/`](../../fixtures/conformance/error-enum-empty-values/) — empty `@values` rejected
242+
- [`fixtures/conformance/error-enum-duplicate-member/`](../../fixtures/conformance/error-enum-duplicate-member/) — duplicate member symbols rejected
243+
- [`fixtures/conformance/error-enum-non-identifier-member/`](../../fixtures/conformance/error-enum-non-identifier-member/) — non-identifier member names rejected
244+
245+
**Embedded value objects (`field.object` + `@storage`)**
246+
247+
- [`fixtures/conformance/field-object-storage-flattened/`](../../fixtures/conformance/field-object-storage-flattened/)`@storage=flattened` owned-type unfurled to columns
248+
- [`fixtures/conformance/field-object-storage-flattened-nullable/`](../../fixtures/conformance/field-object-storage-flattened-nullable/) — nullable owned-type with `@nullable: true`
249+
- [`fixtures/conformance/field-object-storage-jsonb-single/`](../../fixtures/conformance/field-object-storage-jsonb-single/)`@storage=jsonb` single-record column
250+
- [`fixtures/conformance/field-object-storage-jsonb-array/`](../../fixtures/conformance/field-object-storage-jsonb-array/)`@storage=jsonb` on array field
251+
- [`fixtures/conformance/error-field-object-storage-flattened-array/`](../../fixtures/conformance/error-field-object-storage-flattened-array/)`@storage=flattened` on array field is illegal
252+
- [`fixtures/conformance/error-field-object-storage-no-object-ref/`](../../fixtures/conformance/error-field-object-storage-no-object-ref/)`field.object` without `@objectRef` rejected
253+
254+
Cross-port runner coverage: TS / Java / Kotlin / C# / Python all execute these
255+
via their respective conformance runners. See [`docs/CONFORMANCE.md`](../CONFORMANCE.md)
256+
for the per-port pass/skip ledger.
257+
220258
## See also
221259

222260
- [entities.md](entities.md) — host node `object.entity`

docs/features/loaders.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,26 @@ identical bad input. See
164164
for the full enumeration; every entry has a matching `fixtures/conformance/error-*`
165165
fixture that pins the cross-port behavior.
166166

167+
## Verified by
168+
169+
The following conformance fixtures gate this feature's behavior across ports:
170+
171+
**Basic loader behavior**
172+
173+
- [`fixtures/conformance/loader-basic-single-entity/`](../../fixtures/conformance/loader-basic-single-entity/) — single entity file round-trip
174+
- [`fixtures/conformance/loader-basic-empty-package/`](../../fixtures/conformance/loader-basic-empty-package/) — empty `package` allowed (top-level namespace)
175+
- [`fixtures/conformance/loader-basic-explicit-subtype/`](../../fixtures/conformance/loader-basic-explicit-subtype/) — explicit `<type>.<subtype>` keying
176+
- [`fixtures/conformance/loader-basic-multi-file-same-package/`](../../fixtures/conformance/loader-basic-multi-file-same-package/) — multiple files in one package
177+
- [`fixtures/conformance/error-parse-malformed-json/`](../../fixtures/conformance/error-parse-malformed-json/) — malformed JSON surfaces a structured parse error
178+
179+
**All `fixtures/conformance/error-*` fixtures** double as a loader-error matrix; see the
180+
[`ERROR-CODES.json`](../../fixtures/conformance/ERROR-CODES.json) enumeration. Each
181+
error code has at least one matching fixture that pins the cross-port behavior.
182+
183+
Cross-port runner coverage: TS / Java / Kotlin / C# / Python all execute these
184+
via their respective conformance runners. See [`docs/CONFORMANCE.md`](../CONFORMANCE.md)
185+
for the per-port pass/skip ledger.
186+
167187
## See also
168188

169189
- [yaml-authoring.md](yaml-authoring.md) — how YAML lowers to canonical JSON

0 commit comments

Comments
 (0)