From 90e8c3ced5dae7c0b6feb89c5a0e29bca2d72ee3 Mon Sep 17 00:00:00 2001 From: slhx agent Date: Tue, 14 Jul 2026 01:09:07 +0200 Subject: [PATCH] test(versioning): pin supported compatibility matrix req: abi/001 req: abi/003 req: v1_release/007 --- PLAN.md | 4 +++- docs/versioning.md | 27 +++++++++++++++++++++++++-- hemx-core/tests/effect_batch.rs | 22 ++++++++++++++++++++++ 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/PLAN.md b/PLAN.md index 88c011b..aad5abf 100644 --- a/PLAN.md +++ b/PLAN.md @@ -71,8 +71,10 @@ encryption, retention, backup, and deployment policy remain host concerns. ## Slice 7 — v1 compatibility and closure - [ ] **User value:** maintainers and adopters receive a reproducible, migration-aware v1 with no known material contradiction and no hidden publication side effect. -- **State:** Active; Slices 1-6 are complete, and publishing remains separately authorized. +- **State:** In progress — the compatibility audit now names the actually supported matrix, replaces the vague migration-fixture gate with checked-in ABI-v1 bytes plus the real legacy durable-record browser migration, and proves all four canonical example packages together. - **Build:** freeze the supported Rust/browser/WASM/integration matrix; reconcile public/generated/Surface/symbol/wire/runtime/persisted-schema compatibility; add migration fixtures; make canonical examples compatibility tests; update the progressive tutorial path; run all local release gates and disposition every P0/P1, advisory, unsafe-code, license, performance, accessibility, and documentation finding. - **Refusals:** no publish, deploy, upload, store submission, speculative feature, or weakening a gate to make it pass. - **Requirements:** `v1_release/001-010`, `versioning/*`, `test/*`, `diag/*`, `performance/*`, `security/008`, and all requirements changed by the preceding slices. - **Proof:** clean-tree formatting, workspace tests, strict all-target Clippy, compile-fail, browser/WASM/offline/multiplayer scenarios, benchmark budgets, approved pinned lockfile audit, requirements proof audit, docs/examples checks, and independent contradiction review all pass with no unresolved P0/P1. + +`cargo test -p hemx-core --test effect_batch compatibility_fixture_accepts_only_the_declared_v1_wire_version -- --exact`, `cargo test -p hemx-wasm --test browser flat_patch_persists_offline_then_uploads_with_same_operation_identity -- --exact`, and `cargo test -p hemx-v0-examples -p hemx-client-local-example -p hemx-kanban-example -p hemx-saas-example --lib --bins` prove the first compatibility gate. Execution cursor: run the remaining Slice 7 release audit gates from the canonical `hemx-xtask test` entry point, resolve only genuine local failures, and record exact blocked external audit tools instead of inventing substitutes. diff --git a/docs/versioning.md b/docs/versioning.md index cb1fb24..066969f 100644 --- a/docs/versioning.md +++ b/docs/versioning.md @@ -39,6 +39,22 @@ An incompatible wire/runtime change must bump the relevant ABI version and cause old pages or old runtimes to refuse partial updates rather than silently applying wrong effects. req: abi/002 req: abi/003 req: abi/004 req: failure/005 +### Supported compatibility matrix + +The v1 support claim is deliberately narrow: + +| Boundary | Supported | Fails closed when | +|---|---|---| +| Rust toolchain | stable Rust, workspace edition 2021 | an unsupported compiler cannot build the workspace | +| Browser/WASM | Firefox browser suite plus the generated real-WASM path | WASM/bootstrap cannot load or bind | +| Effect wire | ABI `1` only | decoding preserves the version, `is_compatible()` is false, and runtimes refuse application | +| Generated resources | one matching build fingerprint | a stale fingerprint receives reload recovery instead of mutation | +| Durable sync | schema `1`; legacy flat schema-1 records upgrade in place | unknown schema or malformed projection is rejected | +| Runtime set | same-tree `hemx-js`, `hemx-wasm`, generated bindings, and framework sync runtime | mismatched assets have no compatibility guarantee | +| Canonical examples | `v0`, Kanban, client-local, and SaaS workspace packages | an example no longer builds or its focused proof fails | + +No support claim is made for untested browser engines, future wire/schema versions, or arbitrary cross-release runtime mixing. req: abi/001 req: abi/003 req: public_api/003 req: v1_release/007 + ### Advanced escape hatches These are public but advanced. They may evolve faster, but every change still @@ -126,15 +142,22 @@ redgate health --strict Before tagging a v1-compatible release: -- `examples/v0` and `examples/saas` compile and test without raw ids, raw effects, +- `examples/v0`, `examples/client_local`, `examples/kanban`, and `examples/saas` + compile and their package tests pass; v0 and SaaS remain the canonical public + surface examples without raw ids, raw effects, selector targeting, manual registries, raw render/lower calls, or user-authored UI JavaScript in the normal path. req: examples/004 req: examples/005 - `docs/diagnostics.md` describes any new common error class in user language. - req: diagnostics/001 req: diagnostics/002 + req: diag/001 req: diag/002 +- The canonical local release gate is `cargo run -p hemx-xtask -- test`; there + are no separate `public-api` or `ownership-check` xtask subcommands. - `docs/recipes/deploy-versioning.md` remains accurate for runtime asset and fingerprint behavior. - Any incompatible generated ABI/runtime change bumps the relevant ABI/fingerprint inputs and has tests for fail-closed behavior. req: abi/005 +- The checked-in ABI-v1 byte fixture in `hemx-core/tests/effect_batch.rs`, the + legacy flat durable-record browser migration, and canonical example package + tests all pass. req: abi/001 req: abi/003 req: v1_release/007 - Advanced APIs touched by the release are still named as escape hatches in docs. - Upgrade notes state whether users must regenerate code, redeploy the helper-provided runtime asset, or change app code. diff --git a/hemx-core/tests/effect_batch.rs b/hemx-core/tests/effect_batch.rs index 96935f4..9e00ead 100644 --- a/hemx-core/tests/effect_batch.rs +++ b/hemx-core/tests/effect_batch.rs @@ -30,6 +30,28 @@ fn effect_batch_wire_round_trips() { assert!(decoded.is_compatible()); } +#[test] +fn compatibility_fixture_accepts_only_the_declared_v1_wire_version() { + // test req: abi/001 req: abi/003 req: v1_release/007 + const V1_EMPTY_BATCH: &[u8] = &[ + 72, 69, 77, 88, // HEMX + 1, 0, // ABI v1 + 0, 0, // reserved + 7, 0, 0, 0, 0, 0, 0, 0, // fingerprint + 0, 0, 0, 0, // zero operations + ]; + assert_eq!( + EffectBatch::from_wire(V1_EMPTY_BATCH).unwrap().to_wire(), + V1_EMPTY_BATCH + ); + + let mut future = V1_EMPTY_BATCH.to_vec(); + future[4] = 2; + let future = EffectBatch::from_wire(&future).unwrap(); + assert_eq!(future.abi_version, 2); + assert!(!future.is_compatible()); +} + #[test] fn encoded_len_covers_every_effect_shape() { let unscoped = ResourceRef::unscoped(ResourceId::new(ResourceKind::Slot, 1));