Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions docs/specs/2026-08-31-plugin-contract-v5.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<diagnostic>`,
`fix(request) -> fix-plan`), тож сьогодні async не покращує нічого.
**Але рішення 1 і 4 це змінюють:** `docgen` як гість кличе LLM через
`llm-call`, а виклик моделі довгий і природно стрімовий. Тобто потреба
зʼявляється не «взагалі», а конкретно — і краще мати платформу під неї до
того, як `docgen` почнуть портувати.

## 11. Що входить у мажор

За практикою `4.0.0` (`world.wit:108-111`): мажор платиться один раз і несе
Expand All @@ -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 самі по собі — зміни форми світу, тобто мажор. Робити їх окремими
релізами означало б ламати шістьох гостей кілька разів замість одного.
Expand Down