Skip to content

Latest commit

 

History

History
220 lines (189 loc) · 14.4 KB

File metadata and controls

220 lines (189 loc) · 14.4 KB

MetaObjects 1.0 readiness checklist

A living checklist for cutting the first stable release. The strategy + the compatibility surface it commits to are in ADR-0035.

Thesis: scaffold-and-own (ADR-0034) shrank the surface 1.0 must keep stable to the metamodel spine + CLI + wire format + the scaffold-and-own contract — the generated code is owned/disposable, so its internals are no longer a public API. The metaobjects-audit skill is the maturity signal that the surface has set. 1.0 is gated less by features than by dropping the breaking-change rate so we can promise "no breaking until 2.0."

Status legend: ✅ done · 🔶 in progress · ⬜ not started · ❓ [RATIFY] decision needed.


A. Strategic decisions (ratify first — they shape everything else)

  • A1. Version-line strategy — RATIFIED 2026-07-02: decouple. npm/PyPI/NuGet 0.15 → 1.0.0, Java/Kotlin 7.7 → 8.0.0 (both forward — Maven cannot go backwards; 1.0.0 < 7.7.1 in every resolver), tied by a shared Metamodel 1.0 spec version (OpenTelemetry / protobuf-editions model; the Java jump is the Angular 2→4 precedent). ADR-0035 §2 (rewritten). Unblocks G1; adds C4.
  • A2. FR-024 declared-API — RATIFIED: DEFER. api.*/operation.*/binding.* stay reserved-but-unregistered post-1.0 (already absent from expected-registry.json; additive to add later). Removes the last candidate for a breaking round → unblocks the quiet period (G3). Tracked in #10.
  • A3. Deprecated codegen-ts/generators export — RATIFIED: REMOVE at the cut. Removed as part of the 1.0/8.0 major bump (G2), not before — removing an export is breaking, so the major absorbs it. Consumers use the meta init-scaffolded owned copies.
  • A4. Cross-port "own your codegen" — RATIFIED: idiomatic + documented. The per-port split (TS meta init; JVM/Python/C# via build config) is intentional, not a parity gap. → D4 written: docs/features/own-your-codegen.md.

B. Compatibility surface (the 1.0 promise)

  • B1. Compat policy publisheddocs/compatibility-policy.md: the covered surface (breaking ⇒ major), what is not covered, the Metamodel-spec-version
    • decouple scheme, and the MINOR-vs-PATCH rule. (Consumer-facing form of ADR-0035 §1.)
  • B2. 0.x → 1.0 migration guide writtendocs/features/migrations/0.x-to-1.0.md: version re-baseline + verify strict-default, jsonb parsed-value, timestamp instant-default, @dbColumnType slim, index.*/@unique removal, passthrough type-preservation (@convert), deprecated-export removal. FR-024 deferred → no declared-API vocab to migrate.

C. Metamodel freeze (the durable spine)

  • C1. registry-conformance enforces the vocabulary byte-identically across all 5 ports.
  • 🔶 C2. No pending vocabulary churn. The metamodel-1.0 vocabulary program (0.15.0/7.7.0; ADR-0036/0037/0038) was the intended pre-1.0 vocabulary finalization — field.uri/field.inet, @stringFormat, instant-default timestamps + @localTime, the @dbColumnType slim, reverse-nav finders — and ADR-0037 now gives a durable framework for any future addition. Only A2 (FR-024) remains open. Audit the registry for anything still experimental.
  • 🔶 C3. The last breaking metamodel/wire move landed in the 0.15.x lineorigin.passthrough is now type-preserving (#185; a divergent field.<subType> or array-ness fails load with ERR_PASSTHROUGH_TYPE_MISMATCH, generalizing/retiring the FR-015 ERR_PARAMETER_REF_PASSTHROUGH_TYPE_MISMATCH; opt out with the acknowledgement-only @convert on origin.passthrough). It followed 0.15.1/7.7.1 — the index.* type + identity.secondary key-purity (ADR-0040; @unique removed → ERR_UNKNOWN_ATTR) — which followed 0.15.0/7.7.0 (the metamodel-1.0 vocabulary program + the ADR-0039 own-accessor fix) and 0.14.0/7.6.0 (verify strict-default, jsonb parsed-value). The passthrough move reset the quiet-period clock — the first no-breaking coordinated release must come after it (see G3).
  • C4. metamodelVersion marker SHIPPED (PR #145, all 5 ports, "0.9"). A single rolled-up spec-version string the loader/registry exposes and every port emits, asserted by the conformance matrix — the artifact that lets packages version independently while all claiming "implements Metamodel 1.0." Pre-cut the value is "0.9" (still 0.x / unstable, but near-final going into the quiet period; decoupled from every package line); the cut freezes it as 1.0. Design (agreed 2026-07-02):
    • One rolled-up number, not per-provider. Metamodel 1.0 is a named freeze of the core provider set (distribution-version pattern, à la OTel spec releases / protobuf editions). It is a version tag on the existing fixtures/registry-conformance/expected-registry.json manifest — which is already the byte-exact bill of materials every port is gated against — not a new per-provider versioning system. Per-provider precision lives in that manifest, machine-checked, never human-tracked.
    • Registry/runtime property, NOT a per-file stamp. It does not go in the YAML/JSON metadata documents (validity is decided by the loader's registered providers, so there is no yaml/json duplication to manage). (An optional per-file "targets Metamodel X.Y" is separable and YAGNI for 1.0.)
    • Core vocabulary only. Downstream-added providers are outside the promise (ADR-0023) and do not change this number; an app may version its own providers if it cares — the library's concern is the core set.
    • Scope: pick the exposure API per port (e.g. registry.metamodelVersion), stamp the manifest, assert byte-equality of the string across all five ports in registry-conformance.
  • C5. Adopt the minor-vs-patch cadence rule (ADR-0035 §3, going forward). Trigger is new public surface, not code size: package MINOR only for newly-dependable surface (codegen output, CLI flag, a newly-supported vocab member); package PATCH for bugfix/refactor; the Metamodel spec version bumps only on a shared vocabulary/wire change. The fast 7.3→7.7 minor run was breaking velocity; decouple
    • this rule ends the churn.

D. CLI + scaffold-and-own contract

  • D1. verify strict-by-default + --lax/-Dmeta.lax consistent across all 4 CLI ports (shipped 0.14.0/7.6.0).
  • 🔶 D2. CLI flag surface documented + frozeninit/gen/verify (+ subverbs, --lax, --template-spec, target/output flags) per port, locked against the CLI architecture (ADR-0015) and surfaced in one matrix.
  • 🔶 D3. Scaffold-and-own contract stable (TS) — what meta init scaffolds + the Generator interface owned templates implement. A3 resolved: the deprecated codegen-ts/generators re-export is removed at the cut (G2).
  • D4. "Own your codegen" documented for every port (A4 ratified) — docs/features/own-your-codegen.md: the TS meta init flow + the JVM/Python/C# build-config equivalents, side by side.

E. Cross-port conformance + wire contract

  • E1. All shared corpora green (metamodel, render, persistence, api-contract, registry, verify) on main.
  • E2. Cross-port api-contract jsonb gate wired for all 5 ports (TS/Python + Java/Kotlin/C#).
  • 🔶 E3. Sweep for any per-port-only contract behavior that should be cross-port gated before the freeze. The thesis keeps paying out: the ADR-0039 own-accessor program (0.15.0/7.7.0) added a shared extends-inheritance conformance fixture and its independent cross-port review caught a real latent class the sweep missed (an M:N junction inheriting its identity.reference children was falsely rejected in all three non-TS ports; a Python runtime path dropped an inherited M:N) — assume more lurk, and lead every cross-port fix with a shared fixture.

F. Adoption proof (the audit as readiness signal)

  • F1. metaobjects-audit skill shipped + run against two real deep adopters.
  • 🔶 F2. A real adopter reaches "Deep/Exemplary" with the CI drift gate wired — the strongest evidence the surface is stable enough to promise. (Both audited adopters were Deep; neither had the drift gate enforced in CI yet — closing that on at least one adopter is the proof point.)
  • F3. Fold the audit findings that point at the framework back in (e.g. the jsonb runtime-write gaps the gate surfaced) so 1.0 ships without known adoption friction.

G. Release mechanics for the 1.0 cut

  • G1. Execute A1 (the decoupled cut): npm/PyPI/NuGet →1.0.0, Java/Kotlin →8.0.0, freeze the spec version at Metamodel 1.0 (C4). Both forward; no backwards move on any registry.

  • G2. Remove the deprecated export if A3=remove (one-time).

  • G3. A quiet period — at least one coordinated release after the last breaking move with no metamodel-breaking changes, to prove the rate has actually dropped. Requires A2/FR-024 to land additively or defer.

    CLOCK RESET by 0.24.0 (2026-08-21). The coordinated pre-1.0 breaking batch — ADR-0052 template direction, FR-038 requirement vocabulary, FR-037 R1 @mutability, FR-037 R2 origin.collection — is four metamodel-breaking retirements in one release, and metamodelVersion moved 0.90.10 for the first time ever. So the counter starts again from 0.24.0, and 1.0 now needs at least one coordinated release AFTER it carrying no metamodel-breaking change.

    OPEN — does 0.24.1 (2026-08-24) satisfy this, or reset it again? UNRATIFIED. 0.24.1 was the first coordinated release after 0.24.0, so on the face of it it is the candidate quiet release. Two facts cut against that:

    1. It moved metamodelVersion 0.110.12 — the very axis G3 measures. (0.11 was spent by #342 and 0.12 by #335; one release, one shipped contract number, but the number moved twice inside the window.)
    2. Two previously-LOADING forms stopped loading@fields together with @expr on an index (#342), and @filterable/@sortable on an isArray field (#335 Half B). An adopter who wrote either has to edit metadata to upgrade.

    The argument the other way is the doctrine this project has now applied four times — the 0.19.1 @min clamp, the 0.21.6 like case-sensitivity fix, and both of the above: a correction of previously-wrong acceptance is a bug fix, not a contract change. Neither form was ever validly expressible (one silently threw half of itself away; the other emitted SQL that cannot execute), and in both cases the fix is deleting an attribute that was doing nothing. On that reading 0.24.1 carried no metamodel-breaking change and G3 is satisfied.

    Recommendation (not a ruling — this is the maintainer's call): treat 0.24.1 as NOT satisfying G3, and require one more coordinated release with no metamodelVersion move. Two reasons. G3's stated purpose is "to prove the rate has actually dropped" — it measures churn in the contract, and a release that moves metamodelVersion and forces adopter edits is evidence the rate has not dropped, whatever the edits are called. And the cost of being wrong is asymmetric: waiting one release costs a release, while cutting 1.0 off a window that actually was churning spends the 1.0 stability promise itself, which cannot be taken back.

    Whoever rules on this should record it here, in this bullet, rather than in a changelog — it is the gate on G1.

    RULED (2026-08-26, maintainer): 0.24.2 does NOT reset the clock, and IS the quiet release G3 asks for. FR-039 moves metamodelVersion 0.120.13, and that is the axis G3 measures — but the move is ADDITIVE. planned | live | partial keep their meanings and their gates, @supersededBy returns on a status that did not previously exist, and no document that loads on 0.24.1 stops loading. Zero adopters must edit anything.

    G3's stated purpose is "to prove the rate has actually dropped", and the rate it measures is BREAKING churn — the thing that costs an adopter a migration. A release forcing no edits is evidence the rate dropped, not evidence against it. That is the distinction the 0.24.1 discussion above could not settle cleanly, because 0.24.1 did force edits (two previously-loading forms stopped loading) whatever one calls them; 0.24.2 forces none, so the two cases do not need the same answer.

    The asymmetric-cost argument above still applies and is answered rather than waived: the risk of ruling wrongly here is cutting 1.0 off a window that was actually churning. It was not. 0.24.1 is treated as NOT satisfying G3 (per the recommendation), and 0.24.2 — one coordinated release later, additive, adopter-edit-free — is the one that does. So G3 is satisfied by 0.24.2, and G1 is unblocked on this gate.

    This cost was adjudicated, not discovered. The batch was ruled in knowing it would reset this clock, on the reasoning that under ADR-0023's sealed strict registry a retirement has no deprecation shim — so N breaking MINORs mean N adopter migrations, and batching converts four migrations into one. Paying one quiet period to buy that is the trade that was accepted. What would NOT be acceptable is discovering the reset later and treating it as a surprise; it is written here so the next reader sees a decision rather than an accident.

  • G4. Cut Metamodel 1.0 through the releasing skill (RC → smoke → confirm → promote), with the migration guide (B2) + compat policy (B1) published alongside.


Last updated 2026-08-21 (post the 0.24.0 coordinated pre-1.0 breaking batch — ADR-0052 + FR-038 + FR-037 R1/R2 — which reset the quiet-period clock again (G3) and moved metamodelVersion 0.90.10. Earlier: 0.15.1/7.7.1 + 0.15.2; the 0.15.x passthrough type-preservation move (#185) had reset it before — C3/G3; A1 ratified — decouple). Owner: maintainer. Update the status marks as items land; ratify the remaining §A decisions (A2–A4) to unblock the rest.