Skip to content

Commit cab9ab3

Browse files
committed
1.0.0: curated schemas, parity gates, stability policy, version cut
1 parent a75ebdb commit cab9ab3

37 files changed

Lines changed: 3903 additions & 1480 deletions

‎.github/workflows/ci.yml‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,33 @@ jobs:
3939
- run: cargo test
4040
working-directory: crates/validator
4141

42+
# Curated≡vendored parity gate (README "Toward 1.0.0" item 2 / DESIGN.md §2.3).
43+
#
44+
# The de-duplicated curated schemas (schemas/curated/*.json + core.json) are the single sources of
45+
# truth the validator loads; the vendored originals (schemas/vendored/) are the verbatim upstream
46+
# quote. This job enforces the two stay in lock-step:
47+
# 1. Bundler determinism: regenerate schemas/curated/bundled/ from the authored sources and assert
48+
# the committed output is byte-identical — catches "edited core.json but forgot to re-bundle +
49+
# commit". (The Rust-side snapshot drift guard, vendored_parity.rs, is the downstream analog:
50+
# it asserts that same committed bundled output matches the embedded _vendored snapshot.)
51+
# 2. Outcome parity: run the curated≡vendored corpus comparison explicitly so the guarantee is a
52+
# named status check (also exercised by the typescript job's full `npm test`).
53+
curated-parity:
54+
name: Curated parity
55+
runs-on: ubuntu-latest
56+
steps:
57+
- uses: actions/checkout@v4
58+
- uses: actions/setup-node@v4
59+
with:
60+
node-version: "22"
61+
- run: npm ci
62+
- name: Re-bundle curated schemas
63+
run: npm run bundle
64+
- name: Committed bundled output is fresh
65+
run: git diff --exit-code -- schemas/curated/bundled/
66+
- name: Curated ≡ vendored outcome parity
67+
run: npm run test:curated-parity -w @jsonstat-validator/ts
68+
4269
wasm:
4370
name: WebAssembly
4471
runs-on: ubuntu-latest

‎CHANGELOG.md‎

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
All notable changes to **jsonstat-validator** are recorded here. The format is based on
44
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project follows
5-
[Semantic Versioning](https://semver.org/spec/v2.0.0.html). The package is **pre-1.0**: until
6-
`1.0.0` the minor component may carry breaking changes; from `1.0.0` on, SemVer applies normally.
5+
[Semantic Versioning](https://semver.org/spec/v2.0.0.html). From `1.0.0` on, SemVer applies
6+
normally; the full stability commitment (public API, diagnostic-result guarantees, error-code
7+
vocabulary, deprecation policy) is in [`STABILITY.md`](STABILITY.md).
78

89
The error-code vocabulary is versioned **independently** of the package via `meta.ruleSetVersion`
910
(append-only within a major), so consumers branch on the vocabulary, not the package version. See
@@ -13,13 +14,60 @@ The error-code vocabulary is versioned **independently** of the package via `met
1314

1415
Staged for the next release. Not yet published.
1516

16-
### Added
17+
## [1.0.0] - 2026-07-01
18+
19+
The `1.0.0` cut. The work tracked in the README "Toward 1.0.0" section is complete; this release
20+
makes the stability commitments in [`STABILITY.md`](STABILITY.md) — the public `validate()` surface,
21+
the `ValidationResult` shape, and the error-code vocabulary are now stable.
22+
23+
### Added — curated schema architecture (DESIGN.md §2.3)
24+
- A de-duplicated [`schemas/curated/`](schemas/curated/core.json) schema set: one shared
25+
[`core.json`](schemas/curated/core.json) holding all `$defs`, plus four thin per-class files
26+
(`dataset`, `collection`, `dimension`, `index`) that `$ref` into it — replacing the triplicated
27+
definitions the verbatim vendored originals carried.
28+
- [`tools/bundle-schemas.mjs`](tools/bundle-schemas.mjs), which inlines every `$ref` into
29+
self-contained [`schemas/curated/bundled/`](schemas/curated/bundled) output. The TS
30+
([`gen-assets.mjs`](packages/ts/tools/gen-assets.mjs)) and Rust
31+
([`build.rs`](crates/validator/build.rs)) generators now embed the **bundled curated** set, not the
32+
vendored originals. Committed, with a bundler-determinism check in CI.
33+
- The **curated≡vendored structural-parity gate**, proving the de-duplicated set is behaviorally
34+
identical to the verbatim upstream originals on every corpus case:
35+
[`packages/ts/test/curated-parity.test.ts`](packages/ts/test/curated-parity.test.ts) (identical
36+
outcomes + clean Unicode-RegExp compile + self-contained) and its Rust mirror
37+
[`crates/validator/tests/curated_equiv_vendored.rs`](crates/validator/tests/curated_equiv_vendored.rs).
38+
- A dedicated **`curated-parity` CI job**
39+
([`ci.yml`](.github/workflows/ci.yml)) that re-bundles and asserts the committed output is fresh,
40+
then runs the outcome-parity test — the guard against "edited the source, forgot to re-bundle".
41+
- [`STABILITY.md`](STABILITY.md) — the SemVer / `ruleSetVersion` stability commitment artifact for the
42+
1.0.0 cut.
1743
- `readme`, `keywords`, and `categories` metadata to the Rust crate manifest
1844
([`crates/validator/Cargo.toml`](crates/validator/Cargo.toml)) so crates.io renders the README and
1945
surfaces the crate under discovery tags. (`0.3.0` shipped without a `readme`, so its crates.io page
2046
showed "no readme"; this takes effect from the next published version — published versions are
2147
immutable, so `0.3.0` itself cannot be retro-fixed.)
2248

49+
### Fixed
50+
- The vendored `updated` date pattern carried an invalid `\-` RegExp escape (an escaped hyphen, which
51+
is a syntax error under the Unicode flag `u`). The curated set replaces it with a literal `-`,
52+
which matches the identical set of strings. This lets the structural pass compile cleanly under the
53+
default Unicode RegExp, removing the [`unicodeRegExp: false`](packages/ts/src/structural.ts)
54+
workaround in TS and the silent-skip-on-compile-failure fallback in
55+
[`structural.rs`](crates/validator/src/structural.rs) (now a `.expect()`, since the embedded
56+
schemas must compile).
57+
58+
### Changed
59+
- Bumped the package version and `engineVersion` from `0.3.0` to **`1.0.0`** across every surface —
60+
[`@jsonstat-validator/ts`](packages/ts), the [`jsonstat-validate`](cli) CLI,
61+
[`@jsonstat-validator/wasm`](packages/wasm), and the [`jsonstat-validator`](crates/validator) Rust
62+
crate — plus the npm and Cargo lockfiles. `ruleSetVersion` stays `1.0.0` (no rule changes).
63+
- [`@jsonstat-validator/wasm`](packages/wasm) now declares its `@jsonstat-validator/ts` dev dependency
64+
as `^1.0.0`.
65+
- The Rust `_vendored` committed-snapshot drift guard
66+
([`vendored_parity.rs`](crates/validator/tests/vendored_parity.rs)) now asserts the snapshot matches
67+
the **curated/bundled** sources (its actual input), not the vendored originals.
68+
- Rewrote the README "Status" / "Versioning" sections for the 1.0.0 cut; retired the now-complete
69+
"Toward 1.0.0" section.
70+
2371
## [0.3.0] - 2026-06-27
2472

2573
`0.3.0` was chosen over `1.0.0` on purpose — see the README "Status" section: the
@@ -64,6 +112,7 @@ follow-up release.
64112
Initial TypeScript engine, full S/D/C rule set, shared corpus, and the CLI (M1/M2), and the Rust
65113
port with corpus parity (M3). See the git history for details.
66114

67-
[Unreleased]: https://github.com/jsonstat/validator/compare/v0.3.0...HEAD
115+
[Unreleased]: https://github.com/jsonstat/validator/compare/v1.0.0...HEAD
116+
[1.0.0]: https://github.com/jsonstat/validator/releases/tag/v1.0.0
68117
[0.3.0]: https://github.com/jsonstat/validator/releases/tag/v0.3.0
69118
[0.2.0]: https://github.com/jsonstat/validator/releases/tag/v0.2.0

‎README.md‎

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ const result = await validateFile("./my-cube.json");
9393
],
9494
"summary": { "errors": 1, "warnings": 0, "infos": 0, "structuralErrors": 0, "byCode": { "VALUE_LEN_MISMATCH": 1 } },
9595
"options": { /* resolved ValidateOptions */ },
96-
"meta": { "engineVersion": "0.3.0", "ruleSetVersion": "1.0.0", "schemaVersion": "1.05", "durationMs": 3 }
96+
"meta": { "engineVersion": "1.0.0", "ruleSetVersion": "1.0.0", "schemaVersion": "1.05", "durationMs": 3 }
9797
}
9898
```
9999

@@ -347,30 +347,34 @@ input:
347347

348348
Parity is **enforced, not asserted**: one shared [`corpus/cases.json`](corpus/cases.json) drives the
349349
TS and Rust suites and the TS↔Wasm parity test that runs in CI, closing the TS ↔ Rust ↔ Wasm
350-
triangle. A committed-snapshot guard
350+
triangle. The **curated≡vendored** structural-parity gate
351+
([`packages/ts/test/curated-parity.test.ts`](packages/ts/test/curated-parity.test.ts),
352+
[`crates/validator/tests/curated_equiv_vendored.rs`](crates/validator/tests/curated_equiv_vendored.rs),
353+
and the dedicated CI job) proves the de-duplicated [`schemas/curated/`](schemas/curated) set the
354+
validator loads produces identical outcomes to the verbatim [`schemas/vendored/`](schemas/vendored)
355+
originals. A committed-snapshot drift guard
351356
([`crates/validator/tests/vendored_parity.rs`](crates/validator/tests/vendored_parity.rs)) keeps the
352-
Rust `_vendored` copy byte-identical to the repo-root [`rules-manifest.json`](rules-manifest.json)
353-
and [`schemas/vendored/`](schemas/vendored), catching pure-metadata drift the corpus test misses.
357+
Rust `_vendored` copy byte-identical to its sources — [`rules-manifest.json`](rules-manifest.json)
358+
and the bundled curated schemas — catching pure-metadata drift the corpus test misses.
354359
Releases publish via [`release.yml`](.github/workflows/release.yml): npm through Trusted Publishing
355360
(OIDC), and the Rust crate to crates.io through a `CARGO_REGISTRY_TOKEN` secret.
356361

357362
### Versioning
358363

359-
The package is **pre-1.0**. `engineVersion` is `0.3.0`; the error-code vocabulary is versioned
360-
independently via `meta.ruleSetVersion` (`1.0.0`, append-only within a major) so downstream tooling
361-
can branch on the vocabulary rather than the package version — see [`DESIGN.md §4.5`](DESIGN.md).
362-
The public `validate()` surface and result shape are stable in practice, but breaking changes remain
363-
allowed before `1.0.0`.
364+
The package is at **`1.0.0`** — the public `validate()` surface, the `ValidationResult` shape, and
365+
the `Finding`/`Summary` types are now stable: code written against the 1.0.0 API will keep compiling
366+
and producing the same verdicts through all `1.x`. Results carry three independent version axes:
364367

365-
### Toward 1.0.0
368+
- **`engineVersion`** (`1.0.0`) — the validator software itself (npm packages, crate, CLI, Wasm).
369+
- **`ruleSetVersion`** (`1.0.0`) — the error-code vocabulary, versioned **independently** of the
370+
package. Codes are append-only within a major; severity may only tighten (a minor), and removal is
371+
a major. Branch on `meta.ruleSetVersion` when you care about which codes can appear.
372+
- **`schemaVersion`** (`1.05`) — the JSON-stat format revision the validator targets.
366373

367-
Remaining work tracked toward the `1.0.0` cut (see [`CHANGELOG.md`](CHANGELOG.md)):
368-
369-
- `schemas/curated/` de-duplicated schema set, with a curated≡vendored parity test.
370-
- A curated-parity CI job (pending the `curated/` schemas above).
371-
- A written SemVer / `ruleSetVersion` stability policy as the commitment artifact for `1.0.0`.
372-
373-
The M1–M5 milestone history is recorded in [`DESIGN.md §11`](DESIGN.md) and the git log.
374+
The full SemVer commitment — what counts as the stable surface, the diagnostic-result guarantees,
375+
the schema provenance (curated vs vendored), and the deprecation policy — is in
376+
[`STABILITY.md`](STABILITY.md). The M1–M5 milestone history is in [`DESIGN.md §11`](DESIGN.md) and
377+
the git log.
374378

375379
---
376380

0 commit comments

Comments
 (0)