From 3fb0f33ae6a7db0cd97f4c819adc0ba6f70ac647 Mon Sep 17 00:00:00 2001 From: Zach Shallbetter Date: Tue, 21 Jul 2026 20:43:04 -0700 Subject: [PATCH] release: 0.10.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ships FieldHandle.guarantees and completes cross-plane publishing. Breaking (pre-1.0): FieldHandle gains a required 'guarantees' member. Additive for every consumer — reading field.guarantees breaks no calling code — and breaking only for third-party code that implements FieldHandle itself, which must now provide the member. Migration: return the runtime envelope or delegate to a wrapped field; the in-repo implementers FieldLayer and FieldField both delegate and are the reference pattern. A break to a protected symbol is the 0.MINOR position pre-1.0, hence 0.10.0 not a patch. All seven packages bumped to 0.10.0 together; FIELD_VERSION advanced in lockstep across the JS, Swift and Kotlin planes (drift test green). CHANGELOG restructured into a dated [0.10.0] section with the breaking change and its migration called out first, so release.yml renders a correct GitHub release body. Revived the per-version release note at docs/release-notes/0.10.0.md. Corrected two stale version strings the drift had left behind — PUBLISHING.md said 0.9.2, the README citation said 0.9.3. One git tag v0.10.0 now releases npm, Swift (SPM tag) and Kotlin (Maven, via the CI publish job added in #1089) at a single version. typecheck, build, check:api (20 protected, no removals), check:docs, check:links and the full suite all green. --- CHANGELOG.md | 36 ++++++++++++++----- PUBLISHING.md | 2 +- README.md | 4 +-- .../fundamental/core/runtime/FieldSnapshot.kt | 2 +- docs/release-notes/0.10.0.md | 33 +++++++++++++++++ packages/core/package.json | 2 +- packages/core/src/version.ts | 2 +- packages/create/package.json | 2 +- packages/dom/package.json | 2 +- packages/elements/package.json | 2 +- packages/react/package.json | 2 +- packages/three/package.json | 2 +- packages/vanilla/package.json | 2 +- .../Engine/FieldSnapshot.swift | 2 +- 14 files changed, 74 insertions(+), 21 deletions(-) create mode 100644 docs/release-notes/0.10.0.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e156d9c..e3042bed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,19 +7,39 @@ a git tag (see [RELEASING.md](RELEASING.md)). ## [Unreleased] -- **Android artifacts publish from CI on a release tag, at a tag-derived version.** `android.yml` gains a `publish` job (`if: refs/tags/v*`, `packages: write`, Actions `GITHUB_TOKEN` — no personal token) that runs `:fundamental-core:publish :fundamental-compose:publish`. The version is derived from the tag via `-PreleaseVersion` and defaults to a `SNAPSHOT` locally — the hardcoded `version = "0.9.5"` is gone, so a publish can never silently overwrite a release with different code. One `git tag vX.Y.Z` now releases every plane at one version: npm via `release.yml`, Swift via the SPM tag, Kotlin via this. Publication config verified against the local Maven repo before merge. -- **Positioning made consistent site-wide.** The homepage rewrite changed the hero, title and description, but the footer — which renders on *every* page — still read "a readable behavior layer for host objects", so the homepage contradicted itself on the same screen. The `Base.astro` default title carried it too. Both now say "a physics engine for interfaces". The only surviving instance is the changelog entry above, which quotes the old phrase to explain why it was retired; historical records that cite a former term are left intact. +## [0.10.0] — 2026-07-21 -- **Finished retiring the freeze vocabulary across `docs/canonical/`.** The earlier change corrected the authoritative sources but left the wording in nine other canonical documents, where "the freeze contract" and "the frozen surface" still described a promise the project had stopped making. All now say *protected* / *removal-protection*. Four uses of the word are deliberately untouched because they mean something else entirely — `Object.freeze`'d policy clones, "freeze the sim" for reduced motion, "frozen particles" in the poster render mode, and "frozen design history" for the planning archive. A pattern-matched sweep would have broken all four. +The reproducibility envelope ships, and cross-plane publishing is complete: **one `git tag v0.10.0` +now releases npm, Swift (SPM) and Kotlin (Maven/GitHub Packages) in lockstep at a single version.** -- **Homepage leads with the artifact instead of the abstraction.** The hero opened with 227 words before anything moved, and asked a reader to hold six unfamiliar concepts — "a readable behavior layer for host objects" appeared in the kicker, the page title, the meta description *and* the first sentence, all before any evidence. The standfirst is now two sentences that are checkable on the page itself, the strongest of which is **"nothing on this page is animated."** Kicker and title become "a physics engine for interfaces" — a category people already have a slot for. -- **New `#shipped` section: four doors, one core.** [Habitat](https://habitat.fundamental-engine.com) (WebGL, `@fundamental-engine/three`), [Ascent](https://ascent.guide) (iOS, `` + elements, on the App Store), [zachshallbetter.com](https://zachshallbetter.com) (`@fundamental-engine/vanilla`), and the [native parity matrix](https://fundamental-engine.com/docs/api/parity). The renderer-agnostic claim was previously asserted in prose; it is now four links you can open. -- **Cross-plane parity surfaced in the hero meta** — `js · swift · kotlin`, six forces, identical output, checked in CI. It was one clause in a dense paragraph and the word "parity" appeared once on the entire page, despite being the least common thing the project can claim. -- Maturity line corrected: it read *"no external users yet"* while shipping in a published iOS app and a live WebGL game. It now reads "shipping in production apps, no third-party adopters yet" — which is both truer and stronger. +### Breaking (pre-1.0) + +- **`FieldHandle` gains a required `guarantees` member.** **Additive for every consumer** — reading + `field.guarantees` is a new capability and breaks no calling code. **Breaking only for third-party + code that *implements* `FieldHandle` itself**, which must now provide the member. **Migration:** + return the runtime's envelope, or delegate to a wrapped field — the in-repo implementers + `FieldLayer` (`@fundamental-engine/three`) and `FieldField` (`@fundamental-engine/vanilla`) both + delegate, and are the reference pattern. Per the pre-1.0 policy this is the `0.MINOR` position, hence + `0.10.0` rather than a patch. + +### Added - **`FieldHandle.guarantees` — the reproducibility envelope is now queryable.** The runtime's determinism classification, its controlled and **uncontrolled** inputs, the requirements for repeatability, and the cross-plane numeric tolerance were previously stated only inside an unexported experimental module. The first external integrator concluded the runtime was byte-identical across environments and designed replay and shared-state features on that — a reasonable inference from unavailable information. It is `conditionally-deterministic`, `host-geometry` and `body-ordering` are **not** controlled, and cross-plane agreement is a tolerance (`1e-6`), never bit-equality. A drift test asserts the published envelope matches the internal contract declaration, because two statements of one fact diverge unless something checks them. - **New canonical doc: [`coupling-discipline.md`](docs/canonical/coupling-discipline.md).** The rung discipline — couple at the lowest rung that achieves the effect — arrived at independently by two consumer projects that each hit the same wall. Covers rung selection, sampling cadence, the measured cost (fill-rate-bound, not particle-bound; ~1ms against a 16.7ms budget), and **when not to use the field at all**: high-frequency domain telemetry belongs in your own arrays, not in bodies. -- **README: the WebGL door is signposted where architecture decisions get made.** `@fundamental-engine/three` was fully documented in the packages table three-quarters of the way down; two independent readers still recommended hand-building the headless-to-`THREE.Points` bridge that ships in it. + +### Build & release + +- **Android artifacts publish from CI on a release tag, at a tag-derived version.** `android.yml` gains a `publish` job (`if: refs/tags/v*`, `packages: write`, Actions `GITHUB_TOKEN` — no personal token) that runs `:fundamental-core:publish :fundamental-compose:publish`. The version is derived from the tag via `-PreleaseVersion` and defaults to a `SNAPSHOT` locally — the hardcoded `version = "0.9.5"` is gone, so a publish can never silently overwrite a release with different code. One `git tag vX.Y.Z` now releases every plane at one version: npm via `release.yml`, Swift via the SPM tag, Kotlin via this. Publication config verified against the local Maven repo before merge. + +### Docs & site + +- **Homepage leads with the artifact instead of the abstraction.** The hero opened with 227 words before anything moved, and asked a reader to hold six unfamiliar concepts — "a readable behavior layer for host objects" appeared in the kicker, the page title, the meta description *and* the first sentence, all before any evidence. The standfirst is now two sentences that are checkable on the page itself, the strongest of which is **"nothing on this page is animated."** Kicker and title become "a physics engine for interfaces" — a category people already have a slot for. +- **New `#shipped` section: four doors, one core.** [Habitat](https://habitat.fundamental-engine.com) (WebGL, `@fundamental-engine/three`), [Ascent](https://ascent.guide) (iOS, `` + elements, on the App Store), [zachshallbetter.com](https://zachshallbetter.com) (`@fundamental-engine/vanilla`), and the [native parity matrix](https://fundamental-engine.com/docs/api/parity). The renderer-agnostic claim was previously asserted in prose; it is now four links you can open. +- **Cross-plane parity surfaced in the hero meta** — `js · swift · kotlin`, six forces, identical output, checked in CI. +- **Positioning made consistent site-wide.** The footer, which renders on every page, and the `Base.astro` default title still carried the old phrasing after the homepage rewrite; both now say "a physics engine for interfaces". +- **Finished retiring the freeze vocabulary across `docs/canonical/`.** Nine documents still described "the freeze contract" / "the frozen surface"; all now say *protected* / *removal-protection*. Four uses meaning something else entirely (`Object.freeze` clones, reduced-motion "freeze the sim", the poster "frozen particles", "frozen design history") are deliberately untouched. +- **README: the WebGL door is signposted where architecture decisions get made.** `@fundamental-engine/three` was documented three-quarters down the packages table; two independent readers still recommended hand-building the headless-to-`THREE.Points` bridge it already ships. +- Maturity line corrected: it read *"no external users yet"* while shipping in a published iOS app and a live WebGL game. ## [0.9.5] — 2026-07-20 diff --git a/PUBLISHING.md b/PUBLISHING.md index e7d14cd6..7dae8c90 100644 --- a/PUBLISHING.md +++ b/PUBLISHING.md @@ -55,7 +55,7 @@ pnpm --filter "@fundamental-engine/*" publish --access public --no-git-checks -- ## Versioning -All seven published packages are versioned together (currently `0.9.2`). Bump them as one: +All seven published packages are versioned together (currently `0.10.0`). Bump them as one: ```sh pnpm --filter "@fundamental-engine/*" exec npm version --no-git-tag-version diff --git a/README.md b/README.md index 78762679..f65cd453 100644 --- a/README.md +++ b/README.md @@ -617,7 +617,7 @@ build-time tool and ships no runtime JavaScript by default. If you use this work, please cite it via its concept DOI (it always resolves to the latest release): -> Shallbetter, Z. (2026). *Fundamental* (Version 0.9.3) [Computer software]. +> Shallbetter, Z. (2026). *Fundamental* (Version 0.10.0) [Computer software]. > Zenodo. https://doi.org/10.5281/zenodo.20989937
@@ -629,7 +629,7 @@ If you use this work, please cite it via its concept DOI (it always resolves to title = {Fundamental}, year = {2026}, publisher = {Zenodo}, - version = {0.9.3}, + version = {0.10.0}, doi = {10.5281/zenodo.20989937}, url = {https://doi.org/10.5281/zenodo.20989937} } diff --git a/android/fundamental-core/src/main/kotlin/com/fundamental/core/runtime/FieldSnapshot.kt b/android/fundamental-core/src/main/kotlin/com/fundamental/core/runtime/FieldSnapshot.kt index 45c54268..9f9d0d2a 100644 --- a/android/fundamental-core/src/main/kotlin/com/fundamental/core/runtime/FieldSnapshot.kt +++ b/android/fundamental-core/src/main/kotlin/com/fundamental/core/runtime/FieldSnapshot.kt @@ -19,7 +19,7 @@ import com.fundamental.core.math.Vec3 * lockstep with the JS constant / the release version: `VersionLockstepTests` fails the build if this * drifts from `packages/core/package.json` (#923) — update it here on every release bump. */ -const val FIELD_VERSION: String = "0.9.5" +const val FIELD_VERSION: String = "0.10.0" /** * Options for [FieldHandle.snapshot] (JS `FieldSnapshotOptions`). Composes with the runtime privacy diff --git a/docs/release-notes/0.10.0.md b/docs/release-notes/0.10.0.md new file mode 100644 index 00000000..3e58ad96 --- /dev/null +++ b/docs/release-notes/0.10.0.md @@ -0,0 +1,33 @@ +# 0.10.0 + +The reproducibility envelope ships, and cross-plane publishing is complete. + +## Headline + +- **`FieldHandle.guarantees`** — the runtime's reproducibility envelope is now a readable property: + determinism classification, controlled and **uncontrolled** inputs, repeatability requirements, and + the cross-plane numeric tolerance. Read it before building replay, shareable state, or + server-authoritative simulation. The answer is `conditionally-deterministic`; `host-geometry` and + `body-ordering` are not controlled; cross-plane agreement is a `1e-6` tolerance, never bit-equality. + +- **One tag, three platforms.** `git tag v0.10.0` now publishes npm (`release.yml`), resolves Swift via + the SPM tag, and publishes Kotlin to GitHub Packages (`android.yml`) — at one version, from CI. + +## Breaking (pre-1.0) + +`FieldHandle` gains a **required** `guarantees` member. + +- **Additive for consumers** — reading `field.guarantees` breaks no calling code. +- **Breaking for third-party `FieldHandle` implementers** — they must provide the member. +- **Migration:** return the runtime envelope, or delegate to a wrapped field. `FieldLayer` + (`@fundamental-engine/three`) and `FieldField` (`@fundamental-engine/vanilla`) both delegate and are + the reference pattern. + +Per the pre-1.0 policy a break to a protected symbol is the `0.MINOR` position — hence `0.10.0`. + +## Also + +- New canonical doc `coupling-discipline.md` (the rung discipline; when *not* to use the field). +- Homepage and canonical docs rewritten for accuracy; the WebGL door and cross-plane parity surfaced. + +Full detail: [CHANGELOG](../../CHANGELOG.md#0100--2026-07-21). diff --git a/packages/core/package.json b/packages/core/package.json index 4356c616..93736176 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@fundamental-engine/core", - "version": "0.9.5", + "version": "0.10.0", "description": "A reciprocal DOM-physics field — elements bend the field; the field's density bends them back.", "type": "module", "license": "MIT", diff --git a/packages/core/src/version.ts b/packages/core/src/version.ts index 82a2897e..88c586fc 100644 --- a/packages/core/src/version.ts +++ b/packages/core/src/version.ts @@ -4,4 +4,4 @@ * with `packages/core/package.json` by `version.test.ts` (the build fails if they drift), so the * release bump is the single source of truth. */ -export const FIELD_VERSION = '0.9.5'; +export const FIELD_VERSION = '0.10.0'; diff --git a/packages/create/package.json b/packages/create/package.json index d1b2eba4..db40a5fb 100644 --- a/packages/create/package.json +++ b/packages/create/package.json @@ -1,6 +1,6 @@ { "name": "@fundamental-engine/create", - "version": "0.9.5", + "version": "0.10.0", "type": "module", "description": "Scaffold a Fundamental starter — `npm create @fundamental-engine` — vanilla, React, or web-component, contained and signals-first by default.", "keywords": [ diff --git a/packages/dom/package.json b/packages/dom/package.json index 955ce154..8ef54da9 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@fundamental-engine/dom", - "version": "0.9.5", + "version": "0.10.0", "description": "The platform-adjacent layer for Fundamental — native-first registries for measurement, semantic state, feedback, relationships, visual-semantic bindings, and overlays. The browser primitives Fundamental wishes existed, built on the ones it has.", "type": "module", "license": "MIT", diff --git a/packages/elements/package.json b/packages/elements/package.json index d1293207..12555f68 100644 --- a/packages/elements/package.json +++ b/packages/elements/package.json @@ -1,6 +1,6 @@ { "name": "@fundamental-engine/elements", - "version": "0.9.5", + "version": "0.10.0", "description": "Web-component keystone for Fundamental — the custom element + declarative data-body bodies.", "type": "module", "license": "MIT", diff --git a/packages/react/package.json b/packages/react/package.json index 0d344ce6..17649f73 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@fundamental-engine/react", - "version": "0.9.5", + "version": "0.10.0", "description": "React adapter for Fundamental — a reciprocal DOM-physics field as a component + useFieldField hook.", "type": "module", "license": "MIT", diff --git a/packages/three/package.json b/packages/three/package.json index a36c2ab3..f105bc04 100644 --- a/packages/three/package.json +++ b/packages/three/package.json @@ -1,6 +1,6 @@ { "name": "@fundamental-engine/three", - "version": "0.9.5", + "version": "0.10.0", "description": "Three.js authoring surface for Fundamental — run the reciprocal field engine headless and render its swarm as a THREE.Points layer (the particle bridge), plus threeHost() and threeBackend() (a RenderBackend) for binding the engine to a WebGL scene.", "type": "module", "license": "MIT", diff --git a/packages/vanilla/package.json b/packages/vanilla/package.json index cf42b650..8e2824c0 100644 --- a/packages/vanilla/package.json +++ b/packages/vanilla/package.json @@ -1,6 +1,6 @@ { "name": "@fundamental-engine/vanilla", - "version": "0.9.5", + "version": "0.10.0", "description": "Framework-free TypeScript wrapper for Fundamental — the reciprocal DOM-physics field as a typed FieldField class + mountField(), with no custom-element registration and no framework dependency.", "type": "module", "license": "MIT", diff --git a/swift/Sources/FundamentalCore/Engine/FieldSnapshot.swift b/swift/Sources/FundamentalCore/Engine/FieldSnapshot.swift index e4ae5258..c6061fe4 100644 --- a/swift/Sources/FundamentalCore/Engine/FieldSnapshot.swift +++ b/swift/Sources/FundamentalCore/Engine/FieldSnapshot.swift @@ -21,7 +21,7 @@ import Foundation /// mirroring the Kotlin port. Kept in lockstep with the package version (npm `latest`) and the JS /// `FIELD_VERSION`: `VersionLockstepTests` fails the suite if this drifts from /// `packages/core/package.json` (#923) — update it here on every release bump. -public let FIELD_VERSION: String = "0.9.5" +public let FIELD_VERSION: String = "0.10.0" /// Options for ``FieldHandle/snapshot(_:)`` (JS `FieldSnapshotOptions`). Composes with the runtime privacy /// ``FieldPolicy`` and an optional ``SnapshotProfile``, always resolving to the TIGHTEST (most private)