From a review of videre-sdk/src/rt.rs (PR #460) and a rejected proposal to hoist the one-poll future driver into nexum-sdk. The hoist is rejected: chain::block_on is IntoFuture-bounded for alloy's builder types, the two drivers have different failure policies across different trust boundaries, and nexum-sdk is not a synchronous-imports-only crate (http.rs drives a real wasi:io/poll reactor through wstd::runtime::block_on). What is left is a naming and documentation defect in videre-sdk that must be settled before the carve.
Related: #460.
Problem
videre-sdk::rt::complete is misnamed and misdocumented in three ways.
rt implies a runtime or scheduler. There is none: the function polls once. It is also the only abbreviated module name in the workspace, and it collides in meaning with wit_bindgen::rt, a direct dependency of this crate whose rt module is a real guest async runtime (spawn_local, async_support).
complete asserts the future completed, while the signature returns Option<F::Output> precisely because it may not have. Three of five call sites import the function bare and never spell the module, so the function name carries the reading weight.
- The doc comment justifies itself with "guest host imports are synchronous". That is not true of the runtime as a whole:
nexum-sdk's wasi:http path drives futures that genuinely suspend. The invariant this function relies on is narrower and belongs to L2: videre:venue/client@0.1.0 declares plain non-async funcs, so a VenueTransport over the host import resolves on the first poll. The over-broad sentence is what prompted a proposal to move the function to L1, where its warrant does not hold.
Cost of deferring: after the M5 carve this is tag-pinned public API of a separate repo, referenced in the glue emitted by videre-macros, so renaming becomes an additive videre tag plus a shepherd repin.
Proposal
- Drop the
rt module. Move the function into videre-sdk/src/client.rs, beside the VenueTransport seam whose synchronicity it asserts. This mirrors L1's existing scoping, where block_on lives inside chain/provider.rs next to the HostTransport it drives rather than at the crate root.
- Rename it for what it does.
now_or_never matches futures::FutureExt::now_or_never exactly on signature and semantics, in free-function form. poll_once returning Poll<F::Output> is the alternative and reads better at the fold sites, at the cost of colliding with the ComposableCoW domain sense of "poll" in composable-cow/src/poll.rs. Pick one; do not keep complete.
- Rewrite the doc to cite the real warrant:
videre:venue/client@0.1.0 declares plain funcs, so a transport over the host import resolves on the first poll. None means a foreign VenueTransport impl suspended, which the keeper macro folds to Fault::Internal.
- Update the emitted path in
videre-macros/src/keeper.rs:118 and the six call sites.
- While in
sweep.rs: the suspension arm at line 138 returns Ok(()) without calling Retrier, unlike the ClientError::Venue arm at line 172. Either route it through Retrier for consistency or state in the comment why a suspension deliberately consumes no retry budget.
Non-goals
- Hoisting the driver into
nexum-sdk. Rejected above.
- Adding
futures-util as a direct dependency. It already reaches every guest through alloy-provider, so the cost is zero, but the macro glue would then have to name a path that every keeper crate resolves, and a re-export buys nothing over an in-crate function.
- De-asyncing
VenueTransport. Worth recording that today it is pure overhead: all five HostVenues methods are async fn bodies with no awaits over synchronous shims, VenueAdapter declares the same five verbs as plain fn, and the only guest awaits in the tree are ethflow-watcher's venue-client calls. The trait becomes third-party public API at the carve and wasip3 makes the seam genuinely async, so this stays as written. Revisit at the wasip3 move, not before.
Acceptance
- No module named
rt in videre-sdk.
- The driver's doc names
videre:venue/client@0.1.0, not "guest host imports".
videre-macros emits the new path; the keeper macro's sync and async branches are unchanged otherwise.
nexum-sdk::chain::block_on is untouched.
Problem
videre-sdk::rt::completeis misnamed and misdocumented in three ways.rtimplies a runtime or scheduler. There is none: the function polls once. It is also the only abbreviated module name in the workspace, and it collides in meaning withwit_bindgen::rt, a direct dependency of this crate whosertmodule is a real guest async runtime (spawn_local,async_support).completeasserts the future completed, while the signature returnsOption<F::Output>precisely because it may not have. Three of five call sites import the function bare and never spell the module, so the function name carries the reading weight.nexum-sdk'swasi:httppath drives futures that genuinely suspend. The invariant this function relies on is narrower and belongs to L2:videre:venue/client@0.1.0declares plain non-async funcs, so aVenueTransportover the host import resolves on the first poll. The over-broad sentence is what prompted a proposal to move the function to L1, where its warrant does not hold.Cost of deferring: after the M5 carve this is tag-pinned public API of a separate repo, referenced in the glue emitted by
videre-macros, so renaming becomes an additive videre tag plus a shepherd repin.Proposal
rtmodule. Move the function intovidere-sdk/src/client.rs, beside theVenueTransportseam whose synchronicity it asserts. This mirrors L1's existing scoping, whereblock_onlives insidechain/provider.rsnext to theHostTransportit drives rather than at the crate root.now_or_nevermatchesfutures::FutureExt::now_or_neverexactly on signature and semantics, in free-function form.poll_oncereturningPoll<F::Output>is the alternative and reads better at the fold sites, at the cost of colliding with the ComposableCoW domain sense of "poll" incomposable-cow/src/poll.rs. Pick one; do not keepcomplete.videre:venue/client@0.1.0declares plain funcs, so a transport over the host import resolves on the first poll.Nonemeans a foreignVenueTransportimpl suspended, which the keeper macro folds toFault::Internal.videre-macros/src/keeper.rs:118and the six call sites.sweep.rs: the suspension arm at line 138 returnsOk(())without callingRetrier, unlike theClientError::Venuearm at line 172. Either route it throughRetrierfor consistency or state in the comment why a suspension deliberately consumes no retry budget.Non-goals
nexum-sdk. Rejected above.futures-utilas a direct dependency. It already reaches every guest throughalloy-provider, so the cost is zero, but the macro glue would then have to name a path that every keeper crate resolves, and a re-export buys nothing over an in-crate function.VenueTransport. Worth recording that today it is pure overhead: all fiveHostVenuesmethods areasync fnbodies with no awaits over synchronous shims,VenueAdapterdeclares the same five verbs as plainfn, and the only guest awaits in the tree are ethflow-watcher's venue-client calls. The trait becomes third-party public API at the carve and wasip3 makes the seam genuinely async, so this stays as written. Revisit at the wasip3 move, not before.Acceptance
rtin videre-sdk.videre:venue/client@0.1.0, not "guest host imports".videre-macrosemits the new path; the keeper macro's sync and async branches are unchanged otherwise.nexum-sdk::chain::block_onis untouched.