Current truth
The currently published package line is v0.42.0-alpha.6.
The project follows Keep a Changelog and SemVer. Historical entries preserve older names where they describe older releases; current docs use the openElement contract.
The published five-package line — unified product and website surface, sealed export seams.
The eleven-package era — JSR-only, before the collapse. Historical record.
v0.42.0-alpha.6 is the published stable line under the ADR-0119 scoped interface freeze. Patches on the 0.41.x line carry tooling and hygiene fixes only; the frozen surface changes only with a major-version ADR.
The npm beta.1–beta.3 artifacts are withdrawn partial releases, not supported product lines or upgrade targets.
※ Withdrawn partial artifacts (beta.1–beta.3) stay withdrawn from the active release story. History is kept, not rewritten.
The maintained release record lives in docs/release/.
Current truth lives in:
docs/current/VERSION_PLAN.mddocs/current/PACKAGE_SURFACE.mddocs/status/STATUS.mddocs/roadmap/ROADMAP.mdHistorical changelog details remain available through git history and release evidence.
docs/audit/2026-07-28-alpha5-round2-review.md,
issues #576–#593) is closed — five high-severity defects in the morph
client plus the protocol and evidence tail.<form action> now wins over
the page URL on enhanced submits (#576); the popstate guard survives
reloads and bfcache restores (#578); morphed-in islands show the
server render (manual DSD instantiation before insertion, #579);
morph matching is an ordered walk with exact deletion and relocation —
reordered id-keyed lists keep order AND island state (#580); nested
DSD compares normalized on both sides (#582); forms inside
late-hydrating islands get the enhancement listener (#584); a
cancelable open:action-error hook precedes the network-failure
reload (#585); morph fallbacks log a reason in dev (#589).hasEnhancedForms follows relative imports, so an enhanced
form inside a shared component no longer loses the enhancement layer
silently (#577).submit event is not composed and page content lives inside
page-element DSD shadow roots, so the document-level listener never saw
enhanced forms. The client is rewritten around shadow-root submit
interception and shadow-content morphing; the island-survival claims
are now mechanically true (errata appended to the alpha.3/alpha.4
notes).actions;
named-action dispatch is own-key gated; one x-openelement-action
header (true = ActionResult JSON, enhance = HTML morph) with
Vary; an action returning a Response is a contract violation; the
default PRG strips the ?/name marker; every 3xx coerces to 303 on
POST and redirect() validates its status; fetch callers always
receive ActionResult JSON (404/500 included, production-scrubbed);
request-time responses carry Cache-Control: no-store; POST takes the
same error boundary as GET; action POSTs get a 10 MB body limit;
non-GET/POST methods answer 405.data-open-region targeting with
navigation fallback, id-keyed + lookahead identity matching, popstate
reload, open:action-failure restored (cancelable), submitter
name/value preserved in the enhanced body, 500/cross-origin responses
navigate instead of morphing, double-submit guard, fragment
preservation, <details>/media state protection. The full survival
matrix is documented in docs/current/MORPH_CONTRACT.md.check:static-output-freeze); a dev(hono) vs
build(Nitro) parity contract test boots both real servers; the perf
baseline records its environment
(docs/release/v0.42.0-alpha.5-performance.json).customElements polyfill — now shipped to the dev entry);
[...path] request-time routes; zero-island apps with enhanced forms
(the enhancement layer is emitted only when enhanced forms exist, so
island-only sites keep their lean bundle); the starter's /contact
route (it was never shipped in TEMPLATE_FILES) now builds and is
POST-smoked in consumer CI; SPA vs request-time loader/action types
and docs are honest; a CSRF threat-model page ships in the guide./register) and valibot
(/subscribe) run inside fixture actions with 422/303 asserted in three
engines — docs/integrations/validation.md. better-auth and Drizzle
recipes are published as doc-level (honestly marked unverified):
docs/integrations/better-auth.md, docs/integrations/drizzle.md.create starter gains a request-time /contact route exercising
the full loop (rendering: 'dynamic' + action + data-open-enhance),
so starter consumers get the loop out of the box.PACKAGE_SURFACE.md records the 0.42 line additions as unfrozen with
their freeze target.docs/release/v0.42.0-alpha.4-performance.json).data-open-enhance)
now morph the returned document into place instead of reloading —
submission returns the same HTML the no-JS path renders (303/422), the
client morphs it, and history.pushState follows the PRG target.data-open-preserve exempts any subtree; the island client
script is never re-executed by a morph.data-open-region container limits the morph to the
matching region when present.rendering: 'dynamic' routes.fail(4xx, data) returns take the 422 re-render channel with the echo;
successful mutations answer 303 (PRG) — never a 200 render; redirects
thrown from actions coerce to 303; POST without an action is a definedformaction='?/name'
(export const actions = { name(ctx) {...} }); unknown names are a
defined 404.x-openelement-action header) receive the ActionResult
discriminated union (failure/redirect/error); the island client
entry enhances data-open-enhance forms with the same protocol and no
DOM surgery — unhydrated islands are untouched, failure falls back to
the native 422 render unless the page handles open:action-failure.javaScriptEnabled: false and on the JS
enhancement path — Chromium, Firefox and WebKit, 33/33.renderIntent.mode was inert metadata before this release.rendering: 'dynamic' routes skip prerendering, dynamic expansion and
i18n locale prerendering; they are served per request by the generated
dist/server/index.js (nitro-mount over the same SSR bundle), with
dist/server/server-manifest.json recording the partition.mode: 'dynamic' fails the build.requestTimeRoutes; pure-static projects emit
no new artifacts (byte-identical public output proven against the 0.41.2
build: zero HTML/JS/CSS differences).packages/adapter-vite/__fixtures__/request-time/ proves loader data
varies per request and islands hydrate identically to static pages
(Chromium, Firefox and WebKit, 12/12).__headExtras is not defined codegen bug for projects without head extras is fixed too.Loader/LoaderContext/Action/
ActionContext) are unchanged — they already shipped; this alpha wires
the rendering-mode semantics around them.10038c4d).tools/project-constants.ts, and the www truth gate fails a release
until the new release theme is written (the 0.41.1 bump had shipped
alpha.19's theme under the v0.41.1 timeline entry).dist/.openElement magic strings converge on shared
internal/paths.ts constants; tools/lib/fs.ts gains shared
readText/readJson used across ten tooling files.CONTRIBUTING.md records the no-sloppy-imports rationale; stale merged
branches were pruned.defineElement, definePage, buildApp, the package graph, the supported
subpaths and the static/SPA semantics of defineApp; request-time data,
forms, sessions and cache stay explicitly unfrozen until 0.42/0.44.app-vite,
build-context, head-injection, i18n-plugin, plugin,
generated-data-resolver, plugin-mdx, route-manifest,
cli/build-client, cli/build-ssg) — use the root, nitro-mount,
cli/build and sitemap instead (breaking; see the migration guide).docs/release/v0.41.0-migration.md and the site's /guide/migration page.--btn-radius, --badge-radius,
--ui-control-radius: --radius-round → --radius-1, 6px) — visual
breaking change; update screenshots and custom control CSS.x.y.z versions
(prerelease-only before), and the version guards stay honest on a stable
current line.default: true desync),
the popstate redirect-then-block URL fork, and For drift-token separator
collisions; the reflect browser spec joins the Firefox/WebKit smoke gates.SafeHtml/UnsafeHtml/StyleSheetRule leave the root for
real, and the internal open-element-render/open-element-hydration
subpaths are pruned from element exports (breaking type-surface changes;
see the GitHub prerelease notes for migration).HYDRATION_STRATEGIES and the routeInfo contract, sinks
the release executor into release.ts with orchestration tests, and
preserves curated release-note sections so migration records stay in the
durable record.globalThis.Deno/destructuring/npm: patterns.reflect: true static-prop write loop and SSR attribute
overwrite; resolves the root-level <Show>/<For> CSR edge; unifies
prop attribute casing; makes For branch tokens content-sensitive;
fixes client-runtime double hydration; runs router guards on history
traversal; honors prefers-color-scheme in theme-init.'warn'); failed pages never ship
nor enter the ISR manifest; static non-200 outcomes are summarized.renderIntent.streaming,
converges fmt/lint exclusions, and retires stale files and config entries.RenderError diagnostics; the unread hydrationHints
contract is removed.clientOnlyTags chain and dead build-context fields.ACTIVE_EXECUTION_VERSION.publish-existing evidence: records the true previous package
line, rewrites GitHub release notes from completed evidence, and
generates the release closure record automatically.@openelement/element root
to @openelement/element/build-utils, stops exporting internal router
types from the @openelement/app root, and aligns PACKAGE_SURFACE.md
with a machine-checked exports inventory. Breaking surface removals:
element root build utilities (migrate to ./build-utils), app root
RouteConfig/RouterInstance/RouterMode types, adapter-vite
ExternalManifest type and SsgPageOutput.hydrationHints.Show/For branches; hydration validates marker counts and branch tokens
and falls back to client re-render on mismatch.observedAttributes at class-definition time so
attribute-to-signal synchronization works in real browsers..tsx/.jsx island chunks, and normalizes Windows
drive-letter island paths (#460).latest dist-tag invariant for prereleases in the publish
tooling and release verifier.alpha dist-tag with post-publish
Deno, Node ESM, Nitro and third-party Web Component smoke evidence.defineLayout alias; use defineElement with the same
arguments for layout elements.