fix(build): target wasip2, bundle SDK WIT, snake_case schema fields - #649
Conversation
Three fixes enable end-to-end capsule build + install for WIT-driven
IPC topic schemas:
1. Target wasm32-wasip2 instead of wasm32-wasip1 — capsules built
with the new SDK produce Component Model binaries (magic bytes
0d 00 01 00) which require wasip2.
2. Bundle astrid-sdk's shared WIT into the capsule archive:
- Extend pack_capsule_archive with a wit_dir parameter that
recursively adds files under the archive path 'wit/'
- New stage_wit_directory() in rust.rs stages the capsule's own
wit/ (or a stub main package if absent) plus astrid-sdk's
wit/astrid-contracts.wit as a WIT dep (deps/astrid-contracts/)
- find_sdk_contracts_wit() uses cargo-metadata to resolve the
exact astrid-sdk dependency source directory
- Capsule authors can now reference shared contract records via
wit_type without duplicating WIT definitions in every capsule
3. Convert kebab-case WIT field names to snake_case in the baked
JSON Schema to match the serde rename_all = 'snake_case'
convention used by wit_events! generated Rust types on the wire.
Also refactors rust.rs::build() into smaller helper functions to
keep each under the clippy too_many_lines threshold.
Verified end-to-end with capsule-registry.
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces critical updates to the capsule build pipeline to support WIT-driven IPC topic schemas. By shifting to the Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. The target shifts to wasip2, To make the components run true. With WIT files in tow, The schemas now flow, In snake_case, as requested by you. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request updates the Rust capsule builder to target wasm32-wasip2 and introduces a mechanism to stage and bundle WIT files, including shared SDK contracts, into the capsule archive. It also includes a fix for field name conversion in WIT schema generation. I have provided feedback regarding performance optimizations for metadata resolution, redundant allocations, and proper handling of file system metadata to ensure symlink compatibility.
Raw .wasm release assets pre-date the Component Model migration and don't support WIT-driven schemas (no wit/ directory means wit_type references fail at install time). The distribution unit is now the packed .capsule archive, which bundles WASM + manifest + WIT deps. Simplifies install_from_github to two priorities: 1. .capsule archive asset from the latest GitHub release 2. git clone + astrid-build from source Removed: - Priority 1 direct .wasm download via releases/latest/download/ - try_install_from_wasm_asset() fallback (93 lines) - Paired Capsule.toml fetching from raw.githubusercontent.com
Implement a proper content-addressed WIT store at ~/.astrid/wit/ with
dedup, append-only semantics, and admin-gated garbage collection.
Content addressing:
- content_address_wit() now recurses subdirectories (includes deps/
WIT files like astrid-contracts.wit)
- Atomic writes via temp file + rename for concurrent install safety
- Per-capsule wit/ directory deleted after content addressing —
meta.json wit_files map (keyed by relative path) is authoritative
- All capsules that share the same WIT content (e.g. SDK contracts)
store a single blob in ~/.astrid/wit/{blake3}.wit
Append-only / replay preservation:
- capsule remove never touches the WIT store
- Blobs accumulate, preserving full replay of historic capsule states
- Only admin GC prunes unreferenced blobs
Admin GC (astrid wit gc):
- Mark-sweep across ALL principal homes + workspace capsules
- Marks = union of wit_files hashes from every installed meta.json
- Dry-run by default (reports orphans), --force to actually delete
- Walks ~/.astrid/home/*/ for cross-principal completeness
Also removes:
- install_standard_wit() from init — fetched stale per-interface
WIT from unicity-astrid/wit repo, unused by anything. Shared
contracts now bundled into capsule archives by astrid-build.
- try_install_from_wasm_asset() — raw .wasm release asset path
that can't carry wit/ dependencies. Capsule distribution is now
.capsule archive or clone+build.
…follow symlinks - Pass already-resolved cargo Metadata to find_sdk_contracts_wit instead of invoking cargo-metadata twice (1 high) - Use meta.target_directory for staging dir (works in workspaces) - Use entry.metadata() (follows symlinks) instead of file_type() in copy_dir_contents, consistent with archiver behavior - Update CHANGELOG.md with all #649 changes
Linked Issue
Closes #650
Summary
End-to-end fixes for WIT-driven IPC topic schemas: capsule build targets wasip2, bundles SDK shared WIT, uses content-addressed dedup store, and simplifies install paths.
Changes
Build
astrid-buildtargetswasm32-wasip2(waswasm32-wasip1)astrid-sdk's sharedastrid-contracts.witinto capsule archives as a WIT dep viastage_wit_directory()+find_sdk_contracts_wit()(uses cargo-metadata, single invocation)Install
.wasmrelease asset install paths (try_install_from_wasm_asset, direct download). Distribution is.capsulearchive or clone+build.install_standard_wit()from init (fetched old 9-file WIT layout, unused)Content-addressed WIT store
content_address_wit()recurses subdirectories (includesdeps/)wit/deleted after addressing —meta.json.wit_filesis authoritativecapsule removenever touches~/.astrid/wit/astrid wit gcadmin command: mark-sweep across all principal homes + workspace, dry-run by default,--forceto deleteTest Plan
Automated
cargo test --workspacepassesManual
astrid-buildon capsule-registry → archive with Component Model magic + bundled WIT depsastrid capsule installsucceeds, bakes provider-entry schema with snake_case fields~/.astrid/wit/, per-capsulewit/removedastrid wit gcreports 0 orphansChecklist
[Unreleased]