Plan 1: the Rust core runs under wazero, wire-compatible with browser Yjs
A Rust y-crdt crate compiles to plain wasm32-unknown-unknown with a C ABI and zero imports, runs under wazero inside a cgo-free Go binary with no JavaScript host anywhere, and stays byte-compatible with browser yjs in both directions including formatting. The branch was allowed to conclude the architecture was wrong. It does not. Seven tasks: the Rust crate; a Node fixture generator using real yjs; both compatibility directions with the fixtures as a contract; the C ABI; the Go wazero host; and .amadan/ci.d/10-gate. Plus the spec commits recording what execution discovered. What the design did not anticipate: yrs calls std::str::from_utf8_unchecked on wire data (read.rs:137). A mutation fuzz hit it on 0.4-5.1% of single-byte corruptions of our own fixtures -- random bytes are harmless, which is why a naive garbage-input test proves nothing. Not fixable from our layer; contained by the per-document wasm instance, and still to file upstream. That makes the sandbox load-bearing for security rather than only portability: inside wasm the fault is a contained trap where a native build corrupts silently. But the containment claim needed correcting, and the branch's own tests said so: some corrupted updates are silently ACCEPTED, so downstream must not assume document text is valid UTF-8. And a 36-byte corrupted fixture ran apply for 163 real seconds and returned the correct answer -- denial of service invisible to any correctness test. The host now caps execution at 1s; the original 5s never fired for the input it was added for. This is falsification-grade, not production-grade, and says so. ABI v1 has no state export, so trap recovery is capped log replay rather than snapshot restore, and the 4096-update cap would make a longer-lived document unloadable. Blocking before internal/core gets a real caller. Every gate here started out checking something adjacent to its purpose and was corrected: the zero-imports test passed by skipping, the trap test passed against a host that never discarded, the containment fuzz checked liveness while discarding the bytes it compared. A check that reports success without checking is the most repeated finding of this work.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011F5CivVm4CmL9ByfSSAaXA
50 files changed,
+7252
−42
.amadan/README.md+49 −0.amadan/ci.d/10-gate+73 −0.cargo/config.toml+19 −0.gitignore+3 −0AGENTS.md+17 −2clippy.toml+5 −0core/.gitignore+1 −0core/Cargo.lock+583 −0core/Cargo.toml+33 −0core/src/abi.rs+288 −0core/src/bin/emit_update.rs+29 −0core/src/lib.rs+110 −0core/tests/no_host_imports.rs+56 −0core/tests/wasm_trap_containment.rs+624 −0core/tests/wire_compat.rs+191 −0core/vendor/README.md+120 −0core/vendor/fastrand-2.5.0/CHANGELOG.md+140 −0core/vendor/fastrand-2.5.0/Cargo.toml+96 −0core/vendor/fastrand-2.5.0/LICENSE-APACHE+201 −0core/vendor/fastrand-2.5.0/LICENSE-MIT+23 −0core/vendor/fastrand-2.5.0/README.md+110 −0core/vendor/fastrand-2.5.0/benches/bench.rs+141 −0core/vendor/fastrand-2.5.0/src/global_rng.rs+234 −0core/vendor/fastrand-2.5.0/src/lib.rs+736 −0core/vendor/fastrand-2.5.0/tests/char.rs+44 −0core/vendor/fastrand-2.5.0/tests/smoke.rs+357 −0docs/superpowers/plans/2026-08-30-rust-core-wire-compat.md+1340 −0docs/superpowers/specs/2026-08-30-docs-design.md+259 −40fixtures/.gitignore+1 −0fixtures/data/concurrent.expected.json+8 −0fixtures/data/concurrent.update.binbinaryfixtures/data/formatted.expected.json+17 −0fixtures/data/formatted.update.binbinaryfixtures/data/hello.expected.json+8 −0fixtures/data/hello.update.binbinaryfixtures/data/unicode.expected.json+8 −0fixtures/data/unicode.update.binbinaryfixtures/generate.mjs+66 −0fixtures/package-lock.json+61 −0fixtures/package.json+9 −0fixtures/verify-rust.mjs+42 −0go.mod+7 −0go.sum+4 −0internal/core/core.go+524 −0internal/core/core_internal_test.go+441 −0internal/core/core_test.go+104 −0internal/core/testdata/docs_core.wasmbinaryrust-toolchain.toml+4 −0scripts/build-wasm.sh+43 −0scripts/wire-gate.sh+23 −0
.amadan/README.mdLoading diff…
.amadan/ci.d/10-gateLoading diff…
.cargo/config.tomlLoading diff…
.gitignoreLoading diff…
AGENTS.mdLoading diff…
clippy.tomlLoading diff…
core/.gitignoreLoading diff…
core/Cargo.lockLoading diff…
core/Cargo.tomlLoading diff…
core/src/abi.rsLoading diff…
core/src/bin/emit_update.rsLoading diff…
core/src/lib.rsLoading diff…
core/tests/no_host_imports.rsLoading diff…
core/tests/wasm_trap_containment.rsLoading diff…
core/tests/wire_compat.rsLoading diff…
core/vendor/README.mdLoading diff…
core/vendor/fastrand-2.5.0/CHANGELOG.mdLoading diff…
core/vendor/fastrand-2.5.0/Cargo.tomlLoading diff…
core/vendor/fastrand-2.5.0/LICENSE-APACHELoading diff…
core/vendor/fastrand-2.5.0/LICENSE-MITLoading diff…
core/vendor/fastrand-2.5.0/README.mdLoading diff…
core/vendor/fastrand-2.5.0/benches/bench.rsLoading diff…
core/vendor/fastrand-2.5.0/src/global_rng.rsLoading diff…
core/vendor/fastrand-2.5.0/src/lib.rsLoading diff…
core/vendor/fastrand-2.5.0/tests/char.rsLoading diff…
core/vendor/fastrand-2.5.0/tests/smoke.rsLoading diff…
docs/superpowers/plans/2026-08-30-rust-core-wire-compat.mdLoading diff…
docs/superpowers/specs/2026-08-30-docs-design.mdLoading diff…
fixtures/.gitignoreLoading diff…
fixtures/data/concurrent.expected.jsonLoading diff…
fixtures/data/concurrent.update.binLoading diff…
fixtures/data/formatted.expected.jsonLoading diff…
fixtures/data/formatted.update.binLoading diff…
fixtures/data/hello.expected.jsonLoading diff…
fixtures/data/hello.update.binLoading diff…
fixtures/data/unicode.expected.jsonLoading diff…
fixtures/data/unicode.update.binLoading diff…
fixtures/generate.mjsLoading diff…
fixtures/package-lock.jsonLoading diff…
fixtures/package.jsonLoading diff…
fixtures/verify-rust.mjsLoading diff…
go.modLoading diff…
go.sumLoading diff…
internal/core/core.goLoading diff…
internal/core/core_internal_test.goLoading diff…
internal/core/core_test.goLoading diff…
internal/core/testdata/docs_core.wasmLoading diff…
rust-toolchain.tomlLoading diff…
scripts/build-wasm.shLoading diff…
scripts/wire-gate.shLoading diff…