0.1.0: CEM-ML/CEM-QL engine + substrate, custom-element adoption, legacy HTML+XSLT back-compat#22
Merged
Conversation
…em-ql expressions
… policies inject named bindings (e.g. $scope.theme)
* group_by() function
* group_by() function
* strict default plus the dev-profile escape hatch: - Static cem.ql.type_error → module fails to compile, no IR, no cache entry, evaluate() rejects. - Runtime cem.ql.type_error → that evaluation aborts at the failing call (same shape as cem.ql.budget_exceeded). - Default scope policy stamps the static-resolution codes (type_error, unknown_type, unknown_function, unknown_variable) at error so AC-QE-4 routes them to fail-fast. - Dev/debug CLI profile is the only relaxation: opt-in named scope-policy preset that demotes those codes to warning, produces evaluator IR anyway, and substitutes the empty stream at runtime. Explicitly forbidden as the default for non-interactive callers.
* read(uri, acceps) * global accepted types
* - cem: — platform implementation, baked into the host crate, always available, scope policy cannot grant or deny.
- urn:cem: — dynamically registered by plugins or a config-time registry map; available wherever registered, unregistered URIs fail with new
cem.ql.import_unresolved. Scope policy cannot grant/deny (host trust setup decides).
- https: (and other network schemes including http:, file:, plugin transports) — online resources carrying their own schema/content-type, off
by default, gated per-scope via AC-QI-4.
- Both cem: and urn:cem: are reserved — any scope-policy grant naming them is rejected at policy load with new cem.ql.reserved_scheme (prevents
shadowing platform stdlib).
* per-scope interleaved stdlib overlays
* | and the other set operators do no implicit casting. 1 :: integer, 1 :: decimal, 1.0 :: double, "1" :: string are four distinct items. Authors converge types explicitly via .map(double(.)) etc.
* cleared resolved open questions
* schema version
* thread pool size
* 100 ms as batch size for render
* plugin code insulation
* transactional DOM ops
* DOM load/create separated from transform
* schema scoping syntax
* .d.ts format
Build the pure decision-core for FF-4 (AC-P-V-6 / AC-P-6.7) per the BR-VC-9 per-contract run-mode disposition. Deferred (follow-up slice, FF-4 stays tracked): wiring it to the contract ingest paths + threading the run-mode source + the AC-P-V-6 fixture/active flip. - packages/cem-elements/src/lib/disposition.ts — RunMode (application / build-ssr / development) x per-contract class (presentation: templates/tokens/patch-transport; data-security: snapshot-datadom / edge-render-state / privacy-export) -> Disposition (reject / degrade / ignore), with the BR-VC-8 must-understand override (rejects in every mode). Pure + total + no I/O; returns an auditable decision record. - disposition.spec.ts — 41 tests covering the full BR-VC-9 table (build/SSR strict all; development tolerant all; application per-contract) + must-understand override + exhaustive contract classification. Test infrastructure: cem-elements had only the browser Storybook vitest project, so pure-logic units had no node home. Added an isolated vitest.unit.config.mts + `cem-elements:test:unit` nx target (node env, src/**/*.spec.ts), wired into `cem-elements:verify` dependsOn and the CI affected list. Zero changes to the green Storybook setup. Gate map unchanged (6 active / 2 tracked / 0 errors); FF-4 `tracks` note + todo.md updated to record the decision-core is landed and what remains. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Continue the FF-4 build (AC-P-V-6 / AC-P-6.7 per BR-VC-9). FF-4 stays tracked; this adds the version-negotiation layer and the first real ingest wiring on top of last commit's pure decision-core. - disposition.ts: add `ingestContractVersion(payloadVersion, buildVersion, mode, contract)` — parses SemVer, then negotiates: no version → accept (BR-EV-5 expand-phase optional); MAJOR mismatch → must-understand reject (BR-VC-8) in every mode; same MAJOR + higher MINOR → unknown optional features → BR-VC-9 `decideDisposition` (accept iff not reject); else understood → accept; present-but-malformed → reject. +9 unit tests (50 total). - cem-elements.ts: apply it at the snapshot hydration seam (`adoptServerRenderedInstance`) — the data/`datadom` contract is data/security, so an un-understood snapshot version is rejected (diagnostic `cem-element.snapshot_version_rejected`) and hydration falls back to a fresh render rather than trusting unknown fields. New `runMode` runtime option (default `application`; build/SSR + dev hosts override) is the run-mode source seam. Behavior-preserving for existing payloads (version 1.0.0 == build → understood; version-less → accept): all 60 Storybook tests still green, typecheck clean. Gate map unchanged (6 active / 2 tracked / 0 errors). Remaining before the FF-4 active flip (tracks note + todo): edge-render-state ingest, an end-to-end hydration reject-path test, and reconciling AC-P-V-6's namespace wording with the BR-VC-9 contract framing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…gest The second data/security contract ingest seam. readEdgeRenderStateContents now applies ingestContractVersion against EDGE_RENDER_STATE_VERSION before trusting a persisted record: an un-understood schema version (higher MINOR = unknown optional features, or MAJOR mismatch = must-understand) yields a new `schema-version-unsupported` read result rather than honoring/dropping unknown fields from a record written by a newer engine. Run mode is a new optional param (default application; mirrors the snapshot hydration seam). - projection.ts: import the disposition core; add the additive `schema-version-unsupported` variant to EdgeRenderStateContentsReadResult; apply the check at the top of readEdgeRenderStateContents. - projection.disposition.spec.ts: 6 end-to-end tests over an InMemoryEdgeRenderStateStore (understood / version-less accept; higher-MINOR reject in app + build/SSR, degrade in dev; MAJOR mismatch must-understand reject in every mode). Behavior-preserving for existing records (schemaVersion 1.0.0 == build → understood; version-less → accept): 60 Storybook + 56 unit tests green, typecheck clean. FF-4 still tracked (item 2: snapshot hydration reject-path DOM test; item 3: AC-P-V-6 vs BR-VC-9 framing). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a Storybook story (browser DOM) that drives the snapshot hydration ingest seam: a server-rendered instance whose serialized DataIslandSnapshot declares a schema MINOR ahead of SNAPSHOT_SCHEMA_VERSION (unknown optional features on the data/security `datadom` contract). Under the default `application` run mode the BR-VC-9 disposition rejects it — `adoptServerRenderedInstance` records `cem-element.snapshot_version_rejected` and hydration falls back to a fresh client render (the article still materializes). This covers the one ingest call site the unit tests cannot (it needs real DOM + the custom-element lifecycle); the edge contract's read seam is already covered by projection.disposition.spec.ts. 61 Storybook tests (+1) and 56 unit tests green; typecheck clean. FF-4 still tracked pending item 3: reconcile AC-P-V-6's namespace wording with the BR-VC-9 contract framing before the active flip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per the framing reconciliation: FF-4's title matches the BR-VC-9 / AC-P-6.7 run-mode disposition over unknown OPTIONAL features per governed contract, which is built + tested (decision-core + both data/security ingest seams + unit tests + hydration reject story). Its old AC-P-V-6 guard is the parser-side unresolved-namespace verifier, a separate cem_ml concern. - fitness-gates.json: FF-4 status tracked -> active; guards AC-P-V-6 -> BR-VC-9 + AC-P-6.7; backing -> cem-elements:test:unit + cem-elements:test (both CI-wired via `nx affected -t test test:unit`); evidence -> the disposition module + its two spec files; $note records the scope + the parser-side split. Gate map: 7 active / 1 tracked / 0 errors. - ff-gate-run.mjs: splitTargetRef now splits on the FIRST ':' — Nx project names never contain ':' (scopes use '/') but target names can (test:unit, build:css, verify:phase13); lastIndexOf mis-parsed colon-bearing targets. - docs (fitness-functions.md, todo.md): move FF-4 to active with its BR-VC-9 scope; add the parser-side AC-P-V-6 unresolved-namespace disposition as a separate tracked cem_ml follow-up. Remaining tracked: FF-7 (AC-P-6.8 XSLT dispatch) + the parser AC-P-V-6 item. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The parser-side half split out of FF-4: the literal AC-P-V-6 verifier for a region whose namespace resolves to no metadata/schema/rule. Mirrors the proven FF-4 decision-core-first approach in Rust. - packages/cem_ml/src/schema/disposition.rs — pure decision-core: RunMode (application/build-SSR/development) × NamespaceClass (presentation/data-security/unclassified) → Disposition (reject/allow/ ignore) per AC-P-6.7, with a scope-policy override that wins over the mode default and an auditable DispositionDecision record. Build/SSR rejects all; development allows all; application allows presentation, rejects data/security, and conservatively rejects unclassified. `ignore` is only reachable via an explicit override. 7 inline unit tests; clippy-clean; full cem_ml suite green (395). Pure, total, no I/O — exhaustively testable. Remaining (tracked in todo.md): detect an unresolved-namespace region + thread the run mode through the schema machine, apply the outcome, then an AC-P-V-6 fixture + integration test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Complete the parser-side AC-P-V-6 verifier (item 1 of the remaining order): detect an unresolved-namespace region and apply the run-mode disposition end-to-end. - schema/disposition.rs: add `KNOWN_NAMESPACES` (cem core / HTML / SVG) + `is_unresolved_namespace(uri, has_active_schema_source)` predicate (an unbound prefix is the separate unbound_prefix lint, not this). +3 unit tests (10 total). - schema/machine.rs: `CemSchemaMachine::with_run_mode` (non-breaking; default Application) + `apply_unresolved_namespace_disposition`, run at element close (own xmlns already resolved, NsContext still live). Resolves the element's namespace, and when it is unknown with no active schema source emits the disposition: reject → `cem.schema.unresolved_namespace` (Error); allow → `…_allowed`; ignore → `…_ignored` (Info report events). - tests/namespace_disposition_fixtures.rs + examples/cem-ml/namespace-disposition/unknown-namespace.cem: 4 tests — application/build-SSR reject, development allows, known-namespace siblings unaffected (exactly one region across modes). Detection only fires on genuinely-unknown namespace URIs, so all existing fixtures are unaffected: full cem_ml suite green (24 binaries, 0 failures), clippy-clean. Tier A realizes the decision as a diagnostic; deeper drop/foreign-DOM materialization + the scope-policy override source are future work. todo.md item -> done; FF-4 $note updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Begin the last tracked capability (item 2 of the remaining order). Same decision-core-first approach: pure version-pinning + opt-in logic for AC-P-6.8 / AC-P-V-4 / AC-P-V-7, deferring the schema-machine handoff wiring. - packages/cem_ml/src/schema/xslt.rs: - XSL_NAMESPACE (version-stable URI, not a version source) + is_xslt_namespace. - parse_xslt_version (xsl:stylesheet/@Version: MAJOR or MAJOR.MINOR). - resolve_xslt_dispatch — pins the requested version against a CEM-owned ADAPTER_LINE SemVer; consults neither the namespace URI nor the CEM-ML core version, so a core MAJOR bump leaves a dispatched region's pinned identity unchanged (AC-P-V-4). - xslt_region_outcome — explicit opt-in → version-pinned Dispatch (or a VersionError on missing/malformed @Version); no opt-in → the AC-P-V-6 unknown-namespace default disposition (AC-P-V-7), building directly on the parser disposition landed in 3213b8d. 9 unit tests; clippy-clean; full cem_ml suite green (24 binaries). Dispatch/isolation/version-pinning are independent of which XSLT versions the engine can execute (AC-P-6.9, deferred). Remaining (tracked): wire the xsl: namespace into the schema machine to open an isolated Layer-5 handoff on opt-in + thread the opt-in source, then AC-P-V-4/V-7 fixtures + integration tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Complete the last tracked fitness function. Wire AC-P-6.8 XSLT region dispatch into the schema machine and flip FF-7 active — all 8 FFs now active (fitness-gate-map: 8 active / 0 tracked / 0 errors). - schema/machine.rs: `with_xslt_dispatch` opt-in (default off, gates the whole path so existing behavior is unchanged) + `emit_xslt_dispatch`. On opt-in, an element resolving to the XSLT namespace opens a version-pinned region at element-open (so descendants are isolated); `@version` is captured on the root and the dispatch is emitted at the root's close: `cem.handoff.xslt_dispatched` (Info, version-pinned) or `cem.xslt.version_invalid` (Error) for a missing/malformed @Version. Descendants of a dispatched region are isolated — neither CEM-ML interpreted nor subject to the unknown-namespace disposition. Without opt-in the region falls to the AC-P-V-6 default (AC-P-V-7). - schema/xslt.rs: +`is_xslt_namespace` already in place; no change. - tests/xslt_dispatch_fixtures.rs + examples/cem-ml/xslt-dispatch/*.cem: 3 integration tests — opt-in dispatches version-pinned + isolated; no opt-in → unknown-namespace reject; opt-in + no @Version → reject. - fitness-gates.json: FF-7 tracked -> active, backing cem_ml:test, evidence the xslt module + fixtures + test; $note scopes it to AC-P-6.8 dispatch and records AC-P-6.9 execution capability-gating as deferred Tier-C. - docs (fitness-functions.md, todo.md): FF-7 -> active; OQ-2 rollup -> all 8 FFs active / 0 tracked. Opt-in-gated, so no regressions: full cem_ml suite green (25 binaries, 0 failures), clippy-clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stale parent checkboxes: all runtime slices (A, B, C1, C1.5, C2.1–C2.6, D, E) were already [x] and `cem-elements:verify` (the C2.6 gate) is green — re-confirmed this session with the FF-4 disposition + test:unit changes integrated (61 Storybook tests + 8 dependent tasks pass). Flip the C2 and runtime-parent boxes to [x] to match. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Re-ran the full migrated-package gate set with this session's engine changes integrated; all green: - cem-elements:verify — 61 Storybook parity + Edge/SSR fixtures + cem_ml_cli e2e/validate-fixtures + the new test:unit (8 dependent tasks). - @epa-wg/custom-element:verify — build/test/lint + browser smoke (7 tasks). - @epa-wg/cem-theme:build:html. - @epa-wg/cem-theme:verify:phase13 — the prior XSLT blocker, now green after the Option-B generator conversion (live browser-XSLT runtime retired). Legacy + material parity inventories are the docs/stories landed in the sub-items. Flip "Verify the migrated package against all required gates" to [x]. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Author docs/release-readiness-0.1.0.md consolidating the six checklist legs (changelog summary, migration guide pointers, bridge-window support matrix, breaking-change list, npm package-contents check, rollback plan), grounded in this session's verified state and referencing the existing migration/bridge/ publish docs rather than duplicating them. Decisions captured: target 0.1.0 across the three published packages (pre-1.0, no stable-1.0 SemVer promise yet); bridge policy = deprecate-now / remove-next- major (FF-5-gated). npm-contents finding: @epa-wg/custom-element files:["*"] ships 152 files / 3.7 MB incl .vscode + dist-duplicated root sources — recorded as a pre-publish action (keep the CDN-facing root entry; verify with npm pack --dry-run), not blind-fixed; cem-elements + cem-theme pack clean. The remaining work is the maintainer publish actions (the doc's §7 checklist: nx release bump, files tighten, CHANGELOG regen, deprecation notice, tag); todo.md item -> [~] with that handoff. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Verifying the custom-element files-hygiene item surfaced that the earlier
findings were based on the dev source dir, not the published artifact —
corrections to release-readiness-0.1.0.md:
- npm-contents: custom-element publishes from a self-contained dist/ (its own
dist/package.json, imports vendored to ./vendor/...). Packing dist/ yields 80
files / 2.9 MB with NO .vscode/dev cruft — the source files:["*"] is a
dev-manifest non-issue. The earlier "152 files incl .vscode" was the source
dir. Only real stray: a 38 kB vendored tsbuildinfo (optional cleanup).
- Release topology (from nx.json release.groups.cem): the fixed group is
{@epa-wg/cem (private root), cem-theme, cem-components, cem-elements} —
cem-components rides the same 0.1.0 bump (was omitted). custom-element is a
separate repo with its own release; trang-native independent (already 0.1.0).
- §7 checklist updated accordingly; migration-gates item checked off.
User decisions unchanged (0.1.0; deprecate-now/remove-next-major) — applied to
the accurate topology. No code change to the publishable artifacts (the files
"fix" was moot: dist/ is already clean).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…md — placed in the Build & test section since the deprecation is about the generator path, not the consumed CSS. Key points it makes: - Generators (src/lib/css-generators/*.html) no longer use browser-native XSLT 1.0/XPath — they author against the CEM-ML/CEM-QL substrate. - Generated dist/lib/css/*.css is unchanged — anyone who just <link>s the stylesheets is unaffected; only forkers/embedders of generator HTML need to migrate. - Deprecated one major, removed the next (FF-5 gated), with a link to release-readiness-0.1.0.md §4.
- Added str:translate, str:substring, str:substring_before, str:substring_after (strings) and seq:count (sequence) — declarations + evaluator helpers. Registry 50→55. - Engine position() parity: cem:for-each now binds $position (1-based, save/restore for nesting) in render.rs. The converter maps XPath position()→$position. - Key scoping correction: the translate() ×256 was almost all SVG transform=, not the XPath fn; and not is already a cem-ql prefix operator — so the real gap was small.
Runtime (cem-elements.ts): added a legacy-xslt mode. templateMode() detects it (explicit lang="custom-element-xslt" or auto-detection of xsl:/bare for-each/value-of/choose/if/variable); readLegacyXsltSource() does the namespace-split XML re-parse (so xsl:/HTML tags stay distinct, with a fallback to HTML content); compileInlineDeclaration() runs the converter → cemMlSource → the same WASM engine as migrated templates. Adapter (custom-element.js): LEGACY_TEMPLATE_LANG now routes untyped legacy templates through the converter (explicit custom-element-v0 still uses the old DOM bridge). No XSLTProcessor — FF-5 stays green.
…l CEM-ML and rendered on the same cem_ql WASM engine as migrated templates — no browser XSLTProcessor (so the FF-5 forbidden gate stays green). A legacy sample and its CEM-ML twin render identically
…e-event twin
A2 — copied material modules are now a CI requirement: a convert gate
(test-fixtures/material-convert-gate.{html,js}) runs every <template> in
material/components/*.html through the runtime's parseLegacyTemplateSource +
convertLegacyTemplateToCemMl pipeline and fails on unexpected diagnostics;
wired into @epa-wg/custom-element:test/:verify (material/** added to cache
inputs). Allows documented deferred gaps (hasBoolAttribute, Tier-3 constructs).
A3 — interactive slice-event twin (LegacySliceIfOrderingParity): a checkbox
slice drives two <if> blocks, asserting slice-driven re-render + in-order inline
rendering, legacy vs CEM-ML twin.
Supporting fixes:
- Extracted the namespace-split reparse to the exported parseLegacyTemplateSource
in convert.ts so runtime and gate share one pipeline; dropped the now-unused
XSL_NAMESPACE from cem-elements.ts.
- Fixed the converter's bare-name mapping: legacy {name} is a flat attribute
lookup ($name), not datadom.slices.name (slices use //name). This had silently
broken the browser-smoke fixture (was passing from stale cache).
- browser-smoke.js now waits for the async converter->WASM render.
Verified: cem-elements:test:unit 69, cem-elements:test 67 (6 twin stories),
@epa-wg/custom-element:verify, FF-5 PASS. todo.md item closed ([x]).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…stom-element-xslt" as the default legacy route and to define the recommended shared engine
ownership.
- Added the hybrid compatibility recommendation and Tier 1/2/3 scope to docs/custom-element-template-migration-options.md.
- Updated packages/cem-elements/docs/legacy-parity-inventory.md so it matches the current legacy-XSLT converter behavior and next step.
- Tightened packages/custom-element/project.json build inputs so @epa-wg/custom-element rebuilds when cem-elements or cem_ql source changes affect the vendored
runtime.
…custom_element.rs
- Added TS mirror/export used by runtime and gates: packages/cem-elements/src/lib/legacy-xslt/contract.ts
- Wired adapter/runtime to shared constants: packages/custom-element/custom-element.js, packages/cem-elements/src/lib/cem-elements.ts
- Replaced broad material gate with manifest-based requirements and diagnostic budgets: packages/custom-element/test-fixtures/material-convert-gate.js, packages/
custom-element/test-fixtures/legacy-compat-manifest.json
… in docs/custom-element-template-migration-options.md:88 and docs/custom-element-adapter-
boundary.md:231.
- Added bounded engine-side legacy HTML+XSLT lowering in packages/cem_ml/src/legacy_custom_element.rs:187.
- Routed convert --to-format cem --content-type custom-element-xslt through the CEM-ML engine in packages/cem_ml/src/real.rs:446.
- Added a WASM export, convertLegacyCustomElementTemplate, in packages/cem_ml/src/api/wasm.rs:75.
- Added engine fixture gating against the material manifest in packages/cem_ml/src/legacy_custom_element.rs:1354.
- Added CLI coverage in packages/cem_ml_cli/src/dispatch.rs:1097.
- Updated Nx cache inputs so material compatibility fixtures invalidate cem_ml:test.
The CEM-owned legacy HTML+XSLT compatibility contract lives in cem_ml::legacy_custom_element (Rust, authoritative); contract.ts mirrors it for the browser adapter, runtime, and fixture gates. Nothing enforced the "keep the two surfaces aligned" note, so they could silently drift as the engine path catches up. - Add contract.alignment.spec.ts: reads the Rust source and asserts the TS mirror matches (template lang, control-flow / declaration / Tier-3 element sets, supported XPath functions, diagnostic codes). cem-elements:test:unit now 75. - Add the Rust source as a test:unit cache input so a contract change invalidates the guard. Verified: cem_ml (426+) / cem_ml_cli (43) cargo tests + clippy clean, cem-elements:verify, @epa-wg/custom-element:verify, FF-5 PASS — the committed engine-side lowering + shared-contract work is consistent and green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…compiler) The browser legacy-xslt path no longer uses a separate TS converter — it shares the CEM-owned cem_ml::legacy_custom_element compiler with the CLI, SSR, and tests, satisfying the "Recommended Engine Ownership" target. - cem_ql WASM: the cem_ml `convertLegacyCustomElementTemplate` export is auto- linked into the cem_ql module (cem_ql depends on cem_ml); rebuilding cem_ql:build:wasm surfaces it. (A re-export collides on the js_name — comment documents why none is added.) - cem-ql-render.ts: add `convertLegacyTemplate(source)` wrapper; re-exported from the cem-elements index for SSR/gates. - Runtime (cem-elements.ts): legacy-xslt stores raw `legacySource` and lowers it lazily on first render via the engine (`ensureLegacyConverted`, dedup + once- surfaced diagnostics); declaredAttributes=[] (engine seed binds declared attrs). - Material gate: converts via the engine (`convertLegacyTemplate`, async). - Deleted the TS converter (convert.ts, convert.spec.ts); kept contract.ts + contract.alignment.spec.ts (TS mirror + drift guard). - Docs: custom-element-adapter-boundary §"Recommended Engine Ownership" + todo. Verified: cem-elements:test 67 (twin parity now via the engine), :test:unit 62, :verify, @epa-wg/custom-element:verify (material gate + smoke via engine), cem_ml/cem_ql cargo, FF-5 PASS. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rehearsed `nx release version/changelog --dry-run` + per-dist `npm pack --dry-run` (everything short of tag/publish). Findings recorded in release-readiness-0.1.0.md §8: - Conventional-commits will NOT auto-bump (only 5/332 commits since 0.0.14 are conventional) — the release must pass an explicit 0.1.0 specifier. - The auto-generated CHANGELOG is unreliable (omits the 0.1.0 work, mis-anchors its from-ref) — curate from the §2 highlights instead. - Pack contents clean across all four dists (counts refreshed in §5). Fix: cem-components pinned `@epa-wg/cem-theme: "^0.0.14"`, which `^0.1.0` violates (nx preserveMatchingDependencyRanges blocked versioning). Changed to `workspace:^` (matching its cem-elements dep; nx rewrites it at release). The 0.1.0 version dry-run is now warning-free; cem-components builds. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…gets
`dtolnay/rust-toolchain@master` now requires an explicit `toolchain` input and
fails fast ("'toolchain' is a required input") — breaking CI on every PR. Pin to
`@stable` (matching rust-toolchain.toml `channel = "stable"`) and pass the
components (rustfmt, clippy) + target (wasm32-unknown-unknown) the build needs,
in both ci.yml and publish.yml.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The dep-range fix (cem-components depending on @epa-wg/cem-theme via workspace:^ instead of ^0.0.14) changes lockfile resolution; CI runs `yarn --immutable` and rejects an out-of-date lockfile. Regenerated yarn.lock. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`cem_ql:build:wasm` (build-cem-ql-wasm.mjs) requires wasm-bindgen-cli 0.2.122, which the runner didn't have — so the WASM build failed, cascading into cem-elements TS2307 (missing cem_ql/dist/wasm) and all storybook tests. Add a prebuilt install step (taiki-e/install-action) to ci.yml and publish.yml. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
cem-components became affected (workspace:^ dep change) and its typecheck surfaced latent vitest-4 incompatibilities: - tsconfig.spec.json referenced the removed `@vitest/browser/providers/playwright` types subpath (TS2688) — dropped; the config imports the provider from `@vitest/browser-playwright`. - vitest.config.mts used the function form (widened `extends: true` → boolean), and nested root-only options (`watch`, `reporters`, `coverage`) inside per-project `test` blocks (TS2769). Switched to the object form and moved root-only options up. cem-components typecheck/test/lint/build green locally; full run-many typecheck/lint/build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
cem-elements imports the cem_ql WASM bindings via a deep relative path (runtime-support/cem-ql-render.ts → ../../../../../cem_ql/dist/wasm), which Nx can't infer as a project edge — so in a clean CI checkout `cem-elements:build` (tsc) raced ahead of `cem_ql:build:wasm` and failed with TS2307 (missing cem_ql/dist/wasm). Locally it only passed because the wasm was pre-built. Add explicit `dependsOn: cem_ql:build:wasm` to build, typecheck, test, and test:unit (custom-element and cem-theme already declare this edge). Validated by deleting dist/wasm and confirming `nx run cem-elements:build` rebuilds it first. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Brings
develop(332 commits sincemain@ 0.0.14) to the 0.1.0 line.Highlights
verify:phase13green; generateddist/lib/css/*.cssunchanged.<cem-element>substrate (cem-elements) — runtime slices A–E, C2cem_qlWASM lowering, serializable projection boundary, SSR hydration + edge render-state.@epa-wg/custom-elementmonorepo adoption — adapter delegates toCemElementRuntime; the browserXSLTProcessorengine is retired (FF-5 forbids its return).cem_ml::legacy_custom_element, shared by browser/CLI/SSR/tests); material convert gate + TS↔Rust contract-alignment guard.cem-components→cem-themedep-range fix).Release note
Not a release itself — landing the 0.1.0 work. Per the rehearsal (
release-readiness-0.1.0.md §8): the bump needs an explicitnx release version 0.1.0(conventional-commits won't auto-bump), and the CHANGELOG should be curated from §2 (the auto-generated one is unreliable).Verification (local, green)
cem_ml/cem_ql/cem_ml_clicargo + clippy ·cem-elements:verify(incl. twin parity) ·@epa-wg/custom-element:verify·@epa-wg/cem-theme:build:html+verify:phase13· FF-gate map · FF-5 removal-scan.🤖 Generated with Claude Code