feat(sdk): runtime::capsule_set_epoch via astrid:[email protected]#61
feat(sdk): runtime::capsule_set_epoch via astrid:[email protected]#61joshuajbouw wants to merge 1 commit into
Conversation
Bump the contracts pin to the [email protected] superset, move astrid-sys's world to import astrid:sys/[email protected] (latest-only; the superset keeps every @1.0.0 call), and add runtime::capsule_set_epoch() -> CapsuleSetEpoch, a serde-transparent fingerprint of the loaded capsule set that moves on install/removal/upgrade and is restart-stable. Lets a capsule self-heal a set-derived cache on its next turn instead of relying on a per-principal invalidation broadcast.
There was a problem hiding this comment.
Code Review
This pull request updates the sys module interface to version 1.1.0, introducing the capsule-set-epoch function to provide a stable fingerprint of the currently-loaded capsule set. This includes adding the CapsuleSetEpoch struct and capsule_set_epoch helper function to the SDK, updating the WIT definitions, and adjusting the internal imports and dependencies. Feedback suggests making the inner field of CapsuleSetEpoch private to enforce the documented opacity of the type.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)] | ||
| #[serde(transparent)] | ||
| pub struct CapsuleSetEpoch(pub u64); |
There was a problem hiding this comment.
The documentation states that CapsuleSetEpoch is opaque and its only meaning is equality. However, the inner u64 field is currently public (pub u64), which allows external code to directly access, inspect, or manually construct arbitrary epoch values.
To enforce encapsulation and preserve the opaque nature of the token, consider making the inner field private. Since capsule_set_epoch() is defined in the same runtime module, it will still be able to construct the struct, and serde's transparent serialization/deserialization will continue to work seamlessly.
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)] | |
| #[serde(transparent)] | |
| pub struct CapsuleSetEpoch(pub u64); | |
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)] | |
| #[serde(transparent)] | |
| pub struct CapsuleSetEpoch(u64); |
There was a problem hiding this comment.
Pull request overview
Adds a new stable runtime fingerprint API (astrid_sdk::runtime::capsule_set_epoch()) backed by the astrid:[email protected] host interface, enabling capsules to detect loaded-capsule-set changes and self-heal load-derived caches.
Changes:
- Introduces
astrid:[email protected]WIT contract (additive superset) includingcapsule-set-epoch. - Updates
astrid-sysbindings/imports toastrid:sys/[email protected]and fixes the getrandom shim to call the versionedsys1_1_0module. - Adds
runtime::capsule_set_epoch() -> CapsuleSetEpochinastrid-sdkand documents it in the changelog.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| CHANGELOG.md | Documents the new runtime::capsule_set_epoch() API and the [email protected] move. |
| astrid-sys/wit-staging/deps/[email protected]/[email protected] | Adds the astrid:[email protected] additive superset WIT with capsule-set-epoch. |
| astrid-sys/src/lib.rs | Updates capsule world import to astrid:sys/[email protected] and routes getrandom to sys1_1_0::random_bytes. |
| astrid-sdk/src/lib.rs | Switches wit_sys alias to sys1_1_0 and adds CapsuleSetEpoch + capsule_set_epoch() wrapper. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)] | ||
| #[serde(transparent)] | ||
| pub struct CapsuleSetEpoch(pub u64); |
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)] | ||
| #[serde(transparent)] | ||
| pub struct CapsuleSetEpoch(pub u64); | ||
|
|
||
| /// Return a stable fingerprint of the currently-loaded capsule set. |
| beside the cache and re-derive only when it moves — picking up a runtime install without waiting on a | ||
| per-principal invalidation broadcast a backend-mediated principal may never receive. Infallible (`0` | ||
| when the registry is momentarily unavailable). (`unicity-astrid/astrid#982`) |
|
Closing in favour of #1069 (per-principal capsule loading). The capsule-set-epoch primitive assumed a single global loaded capsule set; but principals are on per-principal distributions and versions (loaded per-principal off their own meta.json by content hash). With per-principal loaded sets the tool surface is per-principal by construction — no global epoch, no cross-principal cache — so this primitive is the wrong layer. Superseded; tracked under #1069. |
Summary
Adds
astrid_sdk::runtime::capsule_set_epoch() -> CapsuleSetEpoch, a stable fingerprint of the loaded capsule set, so a capsule can self-heal a load-derived cache (e.g. a describe-fan-out tool list) on its next turn instead of relying on a per-principal invalidation broadcast a backend-mediated principal may never receive. Backs theunicity-astrid/astrid#982fix.Changes
contractssubmodule to theastrid:[email protected]superset.astrid-sys: theworld capsulenow importsastrid:sys/[email protected](latest-only; the superset preserves every@1.0.0call). Fixes the getrandom shim'srandom-bytespath to the version-suffixedsys1_1_0module.astrid-sdk:runtime::capsule_set_epoch()returnsCapsuleSetEpoch— a serde-transparent newtype overu64(opaque; compare for equality). Infallible (0when the registry is unavailable).[Unreleased]entry.Verification
cargo check --workspace,cargo clippy --workspaceclean.astrid-sysbuilds forwasm32-unknown-unknownwithgetrandom_backend="custom"(the capsule build path that exercises the shim).sync-contracts-wit.sh --check) in sync.