diff --git a/docs/specs/2026-08-31-plugin-contract-v5.md b/docs/specs/2026-08-31-plugin-contract-v5.md index 1bf4060eb..a46c31aad 100644 --- a/docs/specs/2026-08-31-plugin-contract-v5.md +++ b/docs/specs/2026-08-31-plugin-contract-v5.md @@ -264,6 +264,99 @@ record manifest { | `docgen` (новий, рішення 1) | `file-reader`, `llm-consumer`, `docgen-stage` | | чотири `coverage-provider` (рішення 3) | `coverage-provider` | +## 10.1. Перехід на WASI 0.3 (`wasm32-wasip3`) — тією самою хвилею + +**Рішення 2026-08-31.** Гості переходять із `wasm32-wasip2` на +`wasm32-wasip3` разом із мажором, а не окремо. + +### Чому зараз, а не потім + +Той самий аргумент, яким обґрунтовано склад мажора: перехід ламає всіх +шістьох гостей і вимагає перезбірки — а мажор `5.0.0` це вже робить. +Зробити окремою хвилею означає перезбирати всіх удруге. + +### Що вже готове, а що ні + +**`wasmtime` не обмежує.** Обидва проєкти на версії 48; різниця лише у +feature-прапорці: + +``` +7n-rules: wasmtime-wasi features = ["p2"] +r-plugin: wasmtime-wasi features = ["p3"] +``` + +Тобто хост уміє P3 сьогодні — треба лише перемкнути прапорець. + +**Ціль існує в компіляторі, але не роздається.** Зміряно 2026-08-31: + +``` +rustc --print target-list | grep wasip → wasip1, wasip1-threads, wasip2, wasip3 +rustup target list | grep wasip → wasip1, wasip1-threads, wasip2 (installed) +``` + +`wasm32-wasip3` компілятор знає, але precompiled `std` через rustup не +роздається. Отже збірка вимагає `-Z build-std` або WASI SDK. + +### Піновані версії (рішення власника 2026-08-31) + +| що | версія | примітка | +|---|---|---| +| WASI | **0.3.1** | `github.com/WebAssembly/WASI/releases` | +| WASI SDK | **мінімум `wasi-sdk-34`** | **фінальний реліз**, не `34.0-rc.2` | +| Rust toolchain | пінований у `rust-toolchain.toml` | зараз файлу немає взагалі — заводиться цією хвилею | + +**Розбіжність із `r-plugin`, яку треба врахувати при переносі.** Сусідній +проєкт стоїть на `wasi-sdk-34.0-rc.2`, і його скрипт добування перевіряє +SHA-256 архіву та `VERSION`-метадані **саме тієї** збірки. Ми пінимо +фінальний `wasi-sdk-34`, тож скрипт переноситься **за формою, не дослівно**: +контрольні суми й очікуваний `VERSION` інші, і копіювання без перерахунку +дало б гейт, що мовчки пропускає не ту збірку — рівно той клас, який ми +виполюємо. + +Мінімум, а не точна версія: `wasi-sdk-34` — нижня межа, новіші мажори SDK +приймаються, старіші відхиляються гучно. + +### Референс уже є в сусідньому репозиторії + +`nitra/r-plugin` збирає гостей під `wasm32-wasip3` сьогодні: пінований +`nightly-2026-08-27` (`rust-toolchain.toml`) плюс WASI SDK 34.0-rc.2 з +перевіркою SHA-256 архіву й `VERSION`-метаданих перед розпакуванням. + +Це головний де-ризикувач рішення: ми не першопрохідці, і робочий взірець +лежить у сусідньому репо тієї ж організації. + +### Побічна знахідка: у нас немає `rust-toolchain.toml` + +`r-plugin` пінить `nightly-2026-08-27`; **у `7n-rules` файлу немає взагалі**, +і збірка йде тим toolchain-ом, що стоїть на машині — сьогодні це +`1.100.0-nightly (bff8e12ff, 2026-08-26)`. + +Тобто ми **вже на nightly, але випадково, а не за рішенням**. Це самостійний +ризик того ж класу, що `KNOWN_PLUGIN_RANGES` (#578): непіноване, доки не +розійдеться. Перехід на P3 робить пінування **обовʼязковим**, а не бажаним — +`-Z build-std` без пінованого каналу невідтворюваний за побудовою. + +### Що з `oci-dist` + +Крейт `oci-dist-package` до `0.2.0` приймав лише `wasm32-wasip3` — засновку +першого споживача (`r-plugin`), яка блокувала нас (§2.101). Послаблення до +списку відомих профілів лишається правильним і після цього рішення: +транспорт зберігає байти й digest, а сумісність профілю — політика того, хто +активує компонент. Те, що обидва споживачі зійдуться на P3, робить +обмеження непотрібним, а не виправданим. + +### Чого P3 нам дає і чого ні + +Головне у WASI 0.3 — **нативний async** (streams/futures у Component Model). +`r-plugin` його потребує: він стрімить UI-рендер із гостя. + +Наші гості синхронні за формою (`detect(batch) -> list`, +`fix(request) -> fix-plan`), тож сьогодні async не покращує нічого. +**Але рішення 1 і 4 це змінюють:** `docgen` як гість кличе LLM через +`llm-call`, а виклик моделі довгий і природно стрімовий. Тобто потреба +зʼявляється не «взагалі», а конкретно — і краще мати платформу під неї до +того, як `docgen` почнуть портувати. + ## 11. Що входить у мажор За практикою `4.0.0` (`world.wit:108-111`): мажор платиться один раз і несе @@ -273,6 +366,8 @@ record manifest { 2. Винесення `run-tool`/`exec-tool` із ядра. 3. Винесення `ecosystem-outdated`/`docgen-render` у слотові світи. 4. Кандидат: видалення `capabilities.network`. +5. Перехід гостей на `wasm32-wasip3` і хоста на `wasmtime-wasi` feature + `p3` (розділ 10.1), разом із пінуванням toolchain. Пункти 2–4 самі по собі — зміни форми світу, тобто мажор. Робити їх окремими релізами означало б ламати шістьох гостей кілька разів замість одного.