Skip to content

0.25.0 — one name, one door

Choose a tag to compare

@dmealing dmealing released this 06 Sep 22:25
· 336 commits to main since this release

Coordinated MINOR across all four registries — npm 0.25.0 · PyPI 0.25.0 · NuGet 0.25.0 · Maven Central 7.25.0. Not one is a version-parity bump: each carries changed product files of its own, and expected-registry.json changed, which forces all four regardless. metamodelVersion moves 0.130.14.

The theme: a name resolved twice by two different mechanisms

The pre-1.0 breaking slot is spent on one defect class wearing different hats — two doors answering one question, disagreeing, and nothing noticing because no gate ever asked them both.

  • A <type>.base node loaded in three ports and failed in two, so one document had two verdicts depending on which toolchain read it. The JVM refusal was accidental — its implementation classes are abstract, so instantiation threw and the message named a missing constructor rather than a rule. It survived because all ten base subtypes sat in the registry corpus's own untestedSubTypes list, exercised by nothing in either direction.
  • A bare {"object": …} was answered by four JSON parsers in three different wrong ways, none of which asked the registry for the type's declared defaultSubTypeOf — which the YAML desugar has always used. So raw JSON and desugared YAML meant different things.
  • A physical database name was spelled independently by every emitter that needed it, so codegen and migrate could name the same index two different things.
  • $apiPrefix was frozen into N entity descriptors at meta gen time by a generator with no business knowing a deployment fact.
  • Three ports decided which source is an object's primary by declaration order rather than by role, and views()[0] let declaration order pick a field's control.

The answer is structural: one door per name. <Entity>Names (all five ports) makes a physical data name exist once per run and generated code reference it; resolveIndexName collapses three resolvers spelling one name; all four JSON parsers consult the registry; an authored <type>.base fails the load everywhere with ERR_ABSTRACT_SUBTYPE_AUTHORED; and the client's base URL moves to the runtime provider.

Breaking changes

Six make previously-working input stop working — each has a migration note in CHANGELOG.md:

  1. An authored <type>.base no longer loads (ERR_ABSTRACT_SUBTYPE_AUTHORED).
  2. $apiPrefix leaves the entity descriptor; the base URL moves to the fetcher provider (baseUrl, optional, default "").
  3. A TPH subtype's $path changes to the address its routes actually serve — it previously named an endpoint that 404s.
  4. <Entity>Names mirrors the metadata tree.
  5. The @metaobjectsdev/sdk/agent-docs subpath is removed; the agent context has one source.
  6. Python's GenConfig.column_naming raises TypeError instead of silently doing nothing.

Two more change what meta gen emits without breaking a load: the five @emit* attributes are retired (narrow at the generator instead), and seven attributes codegen read that no provider registers are removed.

Also in this release

An agent/ docs surface (three pages read before touching a tier) with verify --docs; meta types --format json|toon; expose on both routes generators (#348); imageCell(adapter); a columnNaming lever in the two ports that lacked one; and @schema honoured by every table, view and callable binding.

Two gate lessons are recorded on purpose: the gate over the no-magic gates counted prose as coverage and inverted its own verdict, and four of five of those gates asserted "the fixture loads clean" against a lax loader — each carrying the very line saying a gate whose fixture the loader would reject proves nothing.

Full detail: CHANGELOG.md → 0.25.0.