Skip to content

feat(gust): exec-provider componentizes — WIT-type the taskdisp seam (unblocks gale#224) - #232

Merged
avrabe merged 1 commit into
mainfrom
feat/exec-provider-component
Jul 29, 2026
Merged

avrabe merged 1 commit into
mainfrom
feat/exec-provider-component

Conversation

@avrabe

@avrabe avrabe commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Unblocks gale#224 (the fused OS as one component exporting gust:os).

The blocker

Four of the five gust:os providers already componentize cleanly. exec-provider did not:

exec-provider  core 4334 B  ->  FAILS: module requires an import interface named `env`

It carried one raw import, env.poll_task, and three raw #[no_mangle] exports, and it had no WIT world. Meanwhile interface taskdisp { poll-task: func(id: u32) -> u32; } already existed and is that import — and spawn-provider and timer-provider both import taskdisp while nothing exported it. The hole sat at the centre of the composition graph, which is why gale#224 could not close.

This is a seam defect, not a design one.

The change

  • wit-os/gust-os.wit: add interface exec (admit / poll-round / state) and world exec-provider { import taskdisp; export exec; }
  • exec-provider: move onto the same wit_bindgen::generate! pattern the other four providers use

Verified

wasm-tools component new   -> OK, 7097 B
wasm-tools validate        -> valid component
wasm-tools component wit   -> import gust:os/taskdisp@0.1.0
                              export gust:os/exec@0.1.0

No import outside gust:os/* / gust:hal/*. build-gustos-components.sh still passes for the existing providers; gust_exec_probe still runs green under qemu (both tasks Done, hi-prio first).

No semantic drift

The executor's algorithm, data structures and numeric behaviour are untouched. The lib.rs diff deletes no code — only three comment lines change. The Guest impl forwards to the existing extern "C" bodies rather than restating the marshalling, so the two surfaces cannot diverge, and the #[no_mangle] symbols remain exported because build.rs asserts them and the probe links them.

One consequence, documented not worked around

Re-dissolving today's source flips the object's symbol contract: poll_task becomes defined (the forwarder) and poll-task becomes the undefined seam — the same shape os-ts-cm3.o already has. Whoever regenerates exec-cm3.o must rename the probe's stub to #[export_name = "poll-task"], as gust_os_ts_probe already did. Both directions were checked (current stub -> duplicate-symbol link error; renamed stub -> probe green).

The checked-in exec-cm3.o was deliberately not regenerated: that would bump it off the synth 0.42.0 build whose measurements and defect narrative RESULTS.md documents, which deserves its own reviewable change. The tree is green as committed, and the requirement is recorded in RESULTS.md and at the probe's stub so it cannot be hit silently.

Part of the v0.6.0-rc Research Day cut (M1).

🤖 Generated with Claude Code

https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo

…so gust:os/exec can be fused

exec-provider was the one gust:os provider that could not be shipped as a
component. Its trusted dispatch seam was a raw `(import "env" "poll_task")`,
so `wasm-tools component new` refused it outright:

    error: module requires an import interface named `env`

That is a hard blocker for gale#224 (fuse all gust:os providers into one
component): a provider that only exists as a core module cannot enter the
fuse, so the executor — the capability spawn and timer are both backed by —
was excluded from the delivery unit.

Fix the seam, not the executor. gust-os.wit gains an `exec` interface (the
three functions the crate already exported, kebab-cased, with the same lo/hi
u32 split the synth ARM backend forces) and a `world exec-provider { import
taskdisp; export exec; }`. The crate generates against that world and resolves
the executor's `extern "C" poll_task` through a forwarder into the WIT-typed
`gust:os/taskdisp.poll-task` import — exactly the shim spawn-provider already
uses, and the reason spawn componentizes while exec did not.

    wasm-tools component new  -> ok, 7097 B
    wasm-tools component wit  -> import gust:os/taskdisp@0.1.0
                                 export gust:os/exec@0.1.0

Nothing outside gust:os/* is imported, which is the invariant
build-gustos-components.sh enforces (still green for time-provider; exec is
not added to PROVIDERS here — that is the gale#224 follow-up).

No scheduling logic moved. The `Guest` impl forwards to the existing
`exec_admit`/`exec_poll_round`/`exec_state` bodies rather than restating the
marshalling, so the component and the natively-dissolved object are the same
three bodies reached two ways; those C-ABI symbols stay exported because
benches/gust/build.rs asserts them and gust_exec_probe links them. The diff
against the executor include is empty.

One consequence is recorded rather than papered over: a regenerated exec-cm3.o
now DEFINES `poll_task` and leaves `poll-task` undefined, so gust_exec_probe's
stub must be renamed when that artifact is rebuilt (gust_os_ts_probe already
made this move). Verified both ways on a scratch dissolve; the checked-in
object predates the change, so `cargo run --bin gust_exec_probe` is green as
committed.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@avrabe
avrabe merged commit 31b410e into main Jul 29, 2026
64 checks passed
@avrabe
avrabe deleted the feat/exec-provider-component branch July 29, 2026 12:56
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