Skip to content

fix(release,ui): pack @openelement/ui through the compiled-element intrinsic transform (#1301) - #1302

Merged
SisyphusZheng merged 1 commit into
devfrom
fix/1301-packed-ui-part-program
Sep 4, 2026
Merged

fix(release,ui): pack @openelement/ui through the compiled-element intrinsic transform (#1301)#1302
SisyphusZheng merged 1 commit into
devfrom
fix/1301-packed-ui-part-program

Conversation

@SisyphusZheng

Copy link
Copy Markdown
Member

Problem

The packed npm artifact of @openelement/ui could not be SSR-admitted via the documented packageIslands: ['@openelement/ui'] path. @element/@property are compile-time-only intrinsics (ADR-0143, #1209): their runtime exports in @openelement/element are inert no-ops by design, and the Part Program is produced exclusively by the adapter's open:compiled-element transform, which admits only .tsx modules carrying a canonically bound @element(...) decorator application (packages/adapter-vite/src/internal/compiler/plugin.ts). deno pack transpiles packages/ui/src/*.tsx to .js with TC39 decorator lowering (applyDecs2203R), erasing the decorator applications — so no Part Program can ever register from the packed modules, and SSG fails closed with OE_PROGRAM_MISSING on the first ui component (<open-theme-toggle>).

In-repo consumers (www, the ui-dogfood fixture, the packaged starter) never exercised this: the adapter auto-aliases workspace members to their .tsx source whenever cwd is inside a Deno workspace (packages/adapter-vite/src/workspace-alias.ts), and the packed starter does not consume ui. packages/app / packages/element packed artifacts keep their contract because their public surface is runtime APIs, which transpilation preserves; ui is the only package shipping decorator-authored components.

Owner

Release/pack pipeline (tools/publish-npm.ts) + packed-consumer qualification (tools/consumer-packaged-ui.ts). No product-package ownership change.

Before

  • deno task pack:dry-run packs ui sources directly; the tarball's open-theme-toggle.js contains applyDecs2203R lowering and no __partProgram.
  • A hermetic consumer (scratch dir outside the repo, all five tarballs npm-installed, packageIslands: ['@openelement/ui'], one static route rendering <open-theme-toggle>) fails: build exit 1, OE_PROGRAM_MISSING: admitted nested component <open-theme-toggle> is not registered with a compiled Part Program, static route / -> 500, "SSG failed: static route(s) returned non-200".
  • The same failure reproduces against the published ui-0.44.0-beta.1.tgz.

After

  • The pack pipeline detects packages shipping compiled-element sources and packs them from a staged temporary workspace in which each opted-in component module is replaced by its open:compiled-element compiler output (the same intrinsic transform a consumer's own build runs against workspace source). deno pack then transpiles the compiled form — semantics-preserving — instead of lowering the intrinsics away. Staging relaxes only noImplicitOverride/noImplicitAny for the staged member (the compiler emission drops authored override modifiers and leaves computed-factory params implicitly typed; consumers never typecheck the emission). No .d.ts is emitted today and none is emitted now.
  • The packed open-theme-toggle.js now carries static __partProgram and zero applyDecs; package.json exports/main/dependencies post-processing is byte-identical in behavior.
  • The same hermetic consumer now builds green (exit 0) and dist/index.html contains <open-theme-toggle theme="light"> with its compiled DSD (<template shadowrootmode="open" …>, class="theme-toggle", compiled data-theme="light" sink).
  • New CI-gated qualification deno task consumer:packaged-ui (registered in tools/autoflow/policy.ts, ci + release tiers, ordered after package-artifacts:check which produces the tarballs it installs).

Why-not-second-owner

The alternative owners were rejected per the issue's boundary ruling:

  • Changing the admission contract (packageIslands semantics, manifest schema, module specifiers): unnecessary — the contract is correct; only the packed artifact's content was wrong.
  • Shipping raw .tsx source to npm so consumer builds compile it: deno pack has no keep-source mode; this would also change the published module format and every consumer's resolution contract — an ADR-level change, not a repair.
  • Teaching the compiler to recompile lowered .js: the compiled grammar requires authored TSX; the lowered form is unrecoverable. Also ADR-level.

Running the existing, already-mandatory intrinsic transform earlier in the pipeline (pack time instead of consumer-build time) keeps one compiler, one contract, one owner.

Evidence

  • RED (pre-fix, this branch's new gate): deno task consumer:packaged-ui → exit 1, Packed ui consumer SSG build failed / OE_PROGRAM_MISSING on <open-theme-toggle>.
  • GREEN (post-fix): deno task pack:dry-run exit 0 ([npm] @openelement/ui: packing staged compiler output for 10 compiled element module(s) (#1301)); deno task consumer:packaged-ui exit 0 (packageIslands SSR admission renders the compiled DSD from the packed artifact).
  • Publishability gates: deno task package-artifacts:check exit 0 (publint + attw + ESM-only/host-API scans on all five tarballs); deno task consumer:packaged exit 0 (starter path unchanged).
  • deno task test exit 0 (1818 passed / 0 failed main suite; 150 / 0 supabase starter), deno task workflow:check exit 0, deno fmt/deno lint/deno check clean on changed files.
  • Unit coverage: tools/lib/compiled-pack-staging.test.ts (3 tests: ui modules compile with decorators erased + inline map stripped; non-component packages untouched; staging layout/relaxed options/tarball exclusion).

Scope

  • tools/lib/compiled-pack-staging.ts (new), tools/publish-npm.ts (staging wiring), tools/consumer-packaged-ui.ts (new gate), deno.json (task), tools/autoflow/policy.ts (gate registration + triggers).
  • No changes to packages/*, no frozen-semantics paths (ADR-0122/ADR-0151), no public API or contract change, no new packages.

Risk

  • Pack time for ui increases by one compiler pass over 10 modules (~subsecond); staged deno pack resolves workspace deps from a temporary workspace using the root import map (network/cache for npm deps of @openelement/element, already required by package-artifacts:check's publint/attw steps).
  • If the compiler rejects a ui module at pack time, packing now fails closed (previously the defect shipped silently). Intended.
  • The staged pack emits the same "types not included" warnings as today; no .d.ts regression.

Closes #1301

…trinsic transform (#1301)

The packed npm artifact of @openelement/ui could not be SSR-admitted via
the documented packageIslands path: deno pack transpiles the component
.tsx sources to .js with TC39 decorator lowering (applyDecs2203R), which
erases the compile-time-only @element/@Property intrinsics (ADR-0143 —
their runtime exports are inert no-ops by design). No Part Program
registered from the packed modules, so SSG failed closed with
OE_PROGRAM_MISSING. In-repo consumers never saw this because the adapter
auto-aliases workspace members to source (workspace-alias.ts).

The admission contract is unchanged. The pack pipeline now runs the same
open:compiled-element intrinsic transform a consumer build would run:
packages shipping compiled-element sources are packed from a staged
temporary workspace whose component modules carry the compiler output, so
deno pack transpiles compiled form (semantics-preserving) instead of
lowering the intrinsics away.

Adds consumer:packaged-ui, a CI-gated (ci + release tiers) packed-artifact
consumer qualification: the five pack:dry-run tarballs are installed into
a hermetic scratch consumer outside the repository, a minimal app admits
@openelement/ui via packageIslands, and the prerendered HTML must carry
the compiled DSD for <open-theme-toggle>. RED pre-fix (build fails,
OE_PROGRAM_MISSING), GREEN post-fix.
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant