|
| 1 | +--- |
| 2 | +'@objectstack/spec': minor |
| 3 | +--- |
| 4 | + |
| 5 | +fix(spec): `spec-changes.json`'s aggregate export diff declares the release pair it really spans (#18978) |
| 6 | + |
| 7 | +Clause-②: yes (widening) — one new OPTIONAL key on a published artifact (`aggregate.surfaceScope`) |
| 8 | +and one new optional field on `SpecChangesSchema`. Nothing is renamed, retired or reshaped: the |
| 9 | +schema still ACCEPTS a record without it, every existing key keeps its spelling and meaning, and |
| 10 | +`perMajor` and the `release` section are byte-identical. Contract-review tier. |
| 11 | + |
| 12 | +`aggregate.added` / `aggregate.removed` are not registry-derived. A release-time api-surface diff |
| 13 | +fills them by comparing the artifact being published against the previously **published** one, so |
| 14 | +they span **one release** — while the record they sit in is keyed by protocol major (`from: 10, |
| 15 | +to: 17`) and every entry carries only `since: 17` / `removedIn: 17`, with |
| 16 | +`perMajor[16 → 17].added` at `0` beside it. Nothing in the file distinguished one minor's slice |
| 17 | +from the whole major-boundary delta. |
| 18 | + |
| 19 | +Measured on the published `@objectstack/spec@17.4.0` Release asset: `aggregate.added` = **225**, |
| 20 | +`aggregate.removed` = **51**, every entry `since`/`removedIn` = 17 — and set-identical to a |
| 21 | +recomputed `17.3.0 → 17.4.0` diff of the two tarballs' own `api-surface/` snapshots. It was the |
| 22 | +minor's delta wearing a major's label. |
| 23 | + |
| 24 | +**What ships now.** A record whose export arrays are non-empty carries the version pair they were |
| 25 | +diffed between: |
| 26 | + |
| 27 | +```bash |
| 28 | +jq '.aggregate | {from, to, surfaceScope, added: (.added | length), removed: (.removed | length)}' \ |
| 29 | + node_modules/@objectstack/spec/spec-changes.json |
| 30 | +``` |
| 31 | + |
| 32 | +- `surfaceScope: { fromVersion, toVersion }` present ⇒ `added`/`removed` span exactly that |
| 33 | + published-version pair. ⛔ They are **not** the `from` → `to` major delta, and never were. |
| 34 | +- `surfaceScope` absent ⇒ the record carries no export diff at all and `added`/`removed` are |
| 35 | + empty. ⛔ Read that as "this record does not say", never as "nothing was added between `from` |
| 36 | + and `to`" — the same rule the `release` section already states for itself. |
| 37 | +- `from` / `to` still answer the major-boundary question for `converted` / `migrated`, which are |
| 38 | + registry-derived and unaffected. |
| 39 | + |
| 40 | +**Refused at the producer and at the publish gate, in both directions.** The generator reads the |
| 41 | +previous version off the previous artifact's own `package.json`, omits the arrays loudly when it |
| 42 | +cannot read one, and refuses outright to write a non-empty unlabelled array. |
| 43 | +`scripts/check-release-spec-changes.mjs` — which until now checked the `release` section and not |
| 44 | +the aggregate — recomputes the aggregate's claim from the two tarballs and refuses an absent, |
| 45 | +mislabelled or untrue scope. Its self-test roster grows from 15 batteries to 23. |
| 46 | + |
| 47 | +**Nothing previously honest moved.** The committed registry-only projection and every `perMajor` |
| 48 | +record carry no new key at all; the committed `spec-changes.json` changes on its `$comment` line |
| 49 | +and nowhere else. The published schema is deliberately not narrowed — every manifest published so |
| 50 | +far carries an unscoped diff and must keep parsing. |
0 commit comments