Add `TypedDslxAotPackageBuilder` so several typed DSLX AOT entrypoints
can be emitted into one generated Rust package. Rendering the
participating DSLX modules once and having each runner refer back to
those shared modules lets values move directly between generated runners
without adapter types.
# Problem Solved
Generating one typed DSLX AOT wrapper per entrypoint mints nominally
distinct Rust copies of the same DSLX types. Even when two wrappers
describe the same DSLX struct shape, Rust treats those copies as
different types, so callers cannot pass a value produced by one
generated runner directly into another runner's API.
That makes multi-entrypoint typed AOT consumers awkward to compose and
forces adapter or reconstruction layers where the DSLX model only has
one semantic type.
# Mental model
- The existing single-entry API remains the convenience path for one
wrapper.
- The new package builder collects several entrypoints, typechecks the
participating DSLX modules as one shared universe, emits those DSLX
modules once, and nests each generated runner under the DSLX module that
owns its top function.
- Runner signatures point back to the shared emitted Rust items, so one
generated `Widget` remains the same nominal Rust type across
entrypoints.
# Non-goals
- Do not merge unrelated same-shaped DSLX declarations by layout.
- Do not remove or break the existing single-entry API; it remains as a
compatibility convenience layer.
- Do not fold downstream consumer adoption into this PR.
# Tradeoffs
- The package builder requires all entrypoints to use identical DSLX
conversion options and unique generated entrypoint names so one coherent
shared type universe can be emitted safely.
- Sharing is explicit at package-build time rather than inferred across
independently generated wrapper files, which keeps the nominal-type
boundary clear.
# Architecture
- Adds `TypedDslxAotPackageBuilder` plus package-level output metadata
for the generated Rust source and compiled entrypoints.
- Extracts the single-entry compile path so package generation can reuse
the same AOT artifact build flow before rendering one shared module
tree.
- Builds one package-level typed context and one shared
concrete-specialization set, then emits runner modules beneath their
owning DSLX modules.
# Observability
- There is no new runtime telemetry surface.
- The generated package source and golden fixture make the sharing
boundary inspectable: the runner modules both refer to the same emitted
`shared_widget_types::Widget`.
# Tests
Validation covered the package builder path and the existing
single-entry path:
- `cargo test -p xlsynth --lib aot_builder`
- `cargo test -p xlsynth-aot-test-crate`
The package integration test compiles code that sends one generated
`Widget` from `echo_widget` directly into `bump_widget` without an
adapter, proving nominal sharing rather than only structural similarity.
<!-- spr-stack:start -->
**Stack**:
- ➡ #951
⚠️ *Part of a stack created by
[spr-multicommit](https://github.com/mattskl-openai/spr-multicommit). Do
not merge manually using the UI - doing so may have unexpected results.*
<!-- spr-stack:end -->