Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
25ae5d0
talk: Wasm Research Day 2026 deck, presentable from a tablet
avrabe Aug 4, 2026
1d6a24f
talk: fix the overview, add the code, and calibrate to the published …
avrabe Aug 4, 2026
cba69de
talk: fix the type scale — it was sized like a web page, not a slide
avrabe Aug 4, 2026
4697d0f
talk: presentation-sized type, and slide 5 runs the real dissolve
avrabe Aug 4, 2026
fc850a5
talk: slide 5 shows the whole chain — wac and meld included — on the …
avrabe Aug 4, 2026
ffabdb7
talk: the cost slide now carries the measured response, not just the …
avrabe Aug 4, 2026
9bbc00b
talk: scale the type to slide HEIGHT, so no slide overruns at any aspect
avrabe Aug 4, 2026
98ba9b5
talk: add synth's architecture — where the evidence enters the pipeline
avrabe Aug 4, 2026
e972fa1
talk: all three architectures, readable top-to-bottom, one tab each
avrabe Aug 4, 2026
48aa0a4
talk: show the wsc.facts bytes, and explain what "faster" actually means
avrabe Aug 4, 2026
5d5bdc6
talk: split the dense slides, and stop hiding the controls
avrabe Aug 4, 2026
4e9c386
talk: the fonts were never loading — and a single-file export that ne…
avrabe Aug 4, 2026
f24ee4c
talk: eight factual corrections from an adversarial persona review
avrabe Aug 4, 2026
2859293
talk: state the premise — the code is AI-authored, and that is why th…
avrabe Aug 4, 2026
28a9156
talk: the drone is the north star — move it to the close
avrabe Aug 4, 2026
09712dd
talk: execute the review proposal — and land the sharper version of t…
avrabe Aug 4, 2026
0410e00
talk: cut the drone slide
avrabe Aug 4, 2026
1eaea24
talk: declare the bias on the title slide, where the metaphor actuall…
avrabe Aug 4, 2026
d741578
talk: five corrections from clean-room verification — four of them my…
avrabe Aug 4, 2026
c8791d6
talk: slide 3 was a strawman of a system that ships in billions of units
avrabe Aug 4, 2026
3cc9063
talk: slide-by-slide audit — six slides could not stand on their own
avrabe Aug 4, 2026
1b66202
talk: cut the prior-art slide
avrabe Aug 4, 2026
da619da
talk: unify the four architectures onto one spine, and add scry
avrabe Aug 4, 2026
d0938ce
talk: say what each tool DOES, in plain words, when its tab is selected
avrabe Aug 4, 2026
96c6096
talk: restore the inversion — I deleted the proposal while strengthen…
avrabe Aug 4, 2026
354195c
talk: slide 5 named tools the audience meets eleven slides later
avrabe Aug 4, 2026
a87c03c
talk: fix "composewac" — the sub-label rule never compiled
avrabe Aug 4, 2026
c0938d4
talk: lead on the 8 KB part — every decision answers to one number
avrabe Aug 4, 2026
79070cf
talk: the 8 KB part is the emergency motor controller, not the smalle…
avrabe Aug 4, 2026
f992b0e
talk: the failsafe property is a typed artifact, not a sentence on a …
avrabe Aug 4, 2026
6e7b0b3
talk: name the stack bound as a gap — 2048 of 8192 bytes reserved on …
avrabe Aug 4, 2026
40d6c73
talk: restore the LLVM point — my slide split had silently deleted it
avrabe Aug 4, 2026
b2d32f3
talk: syntax highlighting for source blocks, and restore the DMA seam
avrabe Aug 5, 2026
5ed02d0
talk: say where loom's facts come from — the slide claimed a proof wi…
avrabe Aug 5, 2026
7020578
talk: connect the fact channel to the abstract-interpretation work pr…
avrabe Aug 5, 2026
5bfd97c
talk: correct my own RFC-46 answer — we DO implement it, for the sync…
avrabe Aug 5, 2026
d94dd4f
talk: tag every slide with what it is about — one thing, or a set
avrabe Aug 5, 2026
94b6105
talk: cut the four process slides — wrong venue
avrabe Aug 5, 2026
d390b9b
talk: give the deck a measurable ask, and keep the cut slides as backup
avrabe Aug 5, 2026
5ff1b85
talk: cut the unnamed-credit slide — half-crediting is worse than eit…
avrabe Aug 5, 2026
d3ba012
talk: name the technique on the scry tab — this room knows what it means
avrabe Aug 5, 2026
2b36007
talk: the closing slide gives rather than asks — five minutes is no t…
avrabe Aug 5, 2026
53c299b
talk: promise up front what the close delivers
avrabe Aug 5, 2026
20d97cd
talk: put the speaker on it
avrabe Aug 5, 2026
55c642b
talk: "say" -> "explain" on the promise slide
avrabe Aug 5, 2026
dead194
talk: establish the drone on slide 8, and make 43/45 mean what it mea…
avrabe Aug 5, 2026
1b91b66
talk: speaker notes — every number, what it measures, what it does no…
avrabe Aug 5, 2026
fe800a2
talk: name what synth actually eats, key the colour code, show the fa…
avrabe Aug 5, 2026
d1e1147
talk: state the inversion as a claim, name the exact parts, and end o…
avrabe Aug 6, 2026
77c1ec9
talk: merge the watchdog pair, drop an unexplained acronym, name soft…
avrabe Aug 6, 2026
dfa15eb
talk: the backup slide's heading was a sentence fragment from the merge
avrabe Aug 6, 2026
a98a144
fix(talk): a BOM in main.css silently killed the dark palette in the …
avrabe Aug 6, 2026
e25e465
talk: point the DMA slide at the general shared-memory direction
avrabe Aug 6, 2026
8c09a14
talk: name the question slide 12 answers, and both references
avrabe Aug 6, 2026
7e87c6f
talk: let the outlook run the full slide width, and unstuff slide 12
avrabe Aug 6, 2026
81c5633
Merge remote-tracking branch 'origin/main' into talk/wasm-research-da…
avrabe Aug 6, 2026
1a430e8
site: merge talks + preprints into Publications, and publish the deli…
avrabe Aug 6, 2026
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ target/
node_modules/
test-results/
playwright-report/

# Bundled single-file talk (632 KB of inlined fonts) — rebuild with tools/bundle-talk.py
dist/
static/talk.html
6 changes: 0 additions & 6 deletions content/preprints/_index.md

This file was deleted.

6 changes: 6 additions & 0 deletions content/publications/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
+++
title = "Publications"
description = "Talks and preprints from PulseEngine — conference decks as delivered, and working notes on the verification methodology. Draft, honesty-scoped, and pre-review unless stated otherwise."
template = "publications.html"
sort_by = "date"
+++
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ description = "Treat the AI agent as an untrusted producer whose every output is
date = 2026-07-16
draft = false
template = "paper.html"
aliases = ["/preprints/oracle-gated-agent-loops/"]
[taxonomies]
tags = ["verification", "ai-agents", "how-it-works"]
authors = ["Ralf Anton Beier"]
Expand Down
756 changes: 756 additions & 0 deletions content/publications/wasm-research-day-2026.md

Large diffs are not rendered by default.

222 changes: 222 additions & 0 deletions content/talks/wasm-research-day-2026-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
+++
title = "Speaker notes — every number in the deck"
description = "What each figure in the Wasm Research Day 2026 talk measures, what it does not mean, and where it came from."
date = 2026-08-06
draft = true # deck published, speaker notes deliberately not
template = "page.html"
+++

The title slide promises *every number on these slides says where it came from*.
This is that promise, written down. Open it on a second screen during Q&A.

Each entry is: **what the slide says** → what it actually measures → **what it
does not mean** → where it comes from.

---

## 43 of 45 — slides 19 and 32

**Slide 19** ("Is this the Component Model, or our dialect?") — *43 / 45
canonical-ABI fixtures pass at runtime.*
**Slide 32** (takeaway) — *fuse the graph into one core module and the boundary is
gone; 43 of 45 canonical-ABI fixtures then behave identically.*

**What it measures.** 45 wit-bindgen test fixtures. Each one is a *component
graph* exercising a canonical-ABI feature — strings, lists, records, variants,
options, results, resources, multi-return, flags, enums, type aliases — across
**both directions** of cross-component calls. For each: compose the graph, fuse it
into a single core module, **run it**, and compare the observed behaviour against
the unfused original. 43 behave identically.

This is a **differential execution oracle**, not a validation check. That
distinction matters and is worth saying: a fused module can type-check, pass
`wasm-tools validate`, and still be wrong. Only running it catches that class.

**What it does not mean.**
- Not 43/45 of the Component Model *specification* — it is a fixture pass rate.
- Not "lowered to native and still correct". This is the **fusion** step, run
under a host. The lowering to a native object is a separate stage.
- Not a claim about async, which is rejected rather than tested.

**The two failures.** Three-component resource forwarding chains where the
*intermediate* component re-exports a resource it does not itself define. A known
hard corner of the canonical ABI, not a general weakness.

**Source.** meld's RFC-46 response, and its fixture suite.

---

## The composition figures — slide 6

*5 components → 1 component, 20 741 B → meld fuse → 1 core module, 9 874 B (−52.4%)
→ gustos.o, 4 812 B text, .bss 0 → 3 native functions.*

**What it measures.** The five `gust:os` provider components, composed with `wac`,
fused with `meld fuse --memory shared`, optimized with `loom optimize --passes
inline`, lowered with `synth compile --target cortex-m3 --all-exports
--relocatable`. Sizes by `wc -c` and `arm-zephyr-eabi-size`. The three undefined
symbols are `poll-task`, `read32`, `write32`, by `nm -u`.

**What it does not mean.**
- `.bss 0` is **zero static RAM in the object** — not "this OS needs no RAM".
Stacks and any linear-memory arena are provided by the embedder.
- "3 native functions" is the **seam**, not the trusted base. See slide 20.
- The 52.4% includes deleted component metadata, not only memory merging.

**Correction on the record.** An earlier version of the flow slide said *11 linear
memories*. The composed component has **5**. The 11 came from a grep that also
matched five `(export "memory")` lines and a `canon lift`; meld's own stdout says
"Fusing 11 components", which made the wrong number look right.

---

## 8 bytes of SRAM — slide 9

*A whole flashed image: 6 028 B flash of 131 072 (4.6%), 8 B SRAM of 8 192 (0.1%),
8 184 free.*

**What it measures.** `gust_wdg_silicon` — the firmware flashed for the Cortex-M3 leg (STM32F100RB) — by `arm-zephyr-eabi-size`.

**What it does not mean.** This is the **watchdog silicon test image**: one
dissolved driver plus the minimum to boot and report. It is a **floor, not a
system footprint** — no scheduler, no task set, no application. Say this before
someone asks; the slide says it too.

---

## 2 048 of 8 192 — slide 33 (gaps)

*An OS node reserves 2 048 bytes for its shadow stack, and the budget is asserted
rather than proven.*

**Why it is in the deck.** gale's OS-node builds pass `synth --shadow-stack-size
2048`, and synth's own flag contract says: *"The footprint is ASSERTED (the budget
is trusted), not proven — synth does not yet prove the program's max shadow-stack
depth fits the budget."* scry computes the depth; wiring it is the named next
step. If asked "do you have a stack bound" the answer is **no, and here is exactly
what would give us one**.

---

## The driver seams — slides 17 and 18

*USART: 254 B · 0 SRAM · 3 relocations. DMA: 220 B · 0 SRAM · 6 Kani proofs.*

**What it measures.** `arm-zephyr-eabi-size` on the committed dissolved objects;
`nm -u` for the relocation count; `kani::proof` harness count for the DMA
ownership FSM.

**Correction on the record.** The USART figure was **326 B** in an earlier draft.
That number comes from a results file attributed to a two-year-old toolchain and
no current build reproduces it; the committed object measures 254. The DMA object
is **220 B**, not the 218 that had been circulating.

---

## Three dies — slide 14

*Cortex-M4 and Cortex-M3: IWDG reset CONFIRMED, `RCC_CSR 0x14000000 → 0x34000000`,
`IWDGRSTF=1`. RISC-V: native 271 vs dissolved 499 milliticks/call, 1.839× slower,
correctness IDENTICAL over [0,2047], mismatch 0.*

**What it does not mean.** The two watchdog legs are **one happy path on two
dies**. They do not evidence the cannot-un-start property — the firmware never
attempts an un-start. That property is a source-level Kani proof and stays one.

The ESP32-C3 figure **reproduces** a July measurement using the committed synth
0.40 object; the current toolchain pin is newer, so it is not a measurement of
what we ship today. The re-dissolve is blocked because the `gust_mix` wasm input
is not in the repository.

---

## The fact channel — slides 21 to 23

*Nine bytes: `01 01 01 03 07 03 00 ff 0f`. A guarded memory access: 232 → 104 B.*

**What it measures.** The nine bytes are computed from loom's own emitter
(`build_wsc_facts_payload`): schema version, fact count, kind, function index,
value id, body length, then `lo`/`hi` as signed LEB128. One value-range fact,
function 3, value 7, range [0, 2047].

**What it does not mean.** The 232 → 104 figure is **what the channel does when it
carries a fact** — not evidence that we produce many. The emitter, schema and wire
format are done and byte-verified against the consumer; the *source* that would
populate it at volume is not wired. loom emits **no** `wsc.facts` section by
default.

---

## The clamp — slides 26 to 28

*native LLVM 0.50 ticks/call · dissolved today 0.70 (1.4× slower) · with the proof
0.23 (2.2× faster). And `assert_unchecked` → stock LLVM 30 B → 12 B.*

**What it measures.** `gust_floor_bench`, same harness for all three. The
`assert_unchecked` comparison is rustc → thumbv7m, `opt-level="s"`, lto,
panic=abort.

**The honest headline, volunteered before anyone asks.** The shipping
configuration is **1.4×–1.84× slower than native LLVM**. The 0.23 row is the
proof-carrying path, and it depends on a fact channel whose producer is not wired.

**Correction on the record.** The deck used to claim *"a compiler with no verifier
cannot reach it"*. That is **false** — told the same premise, stock LLVM folds the
clamp identically. What is ours is the *provenance* of the premise:
`assert_unchecked` is unchecked, so a wrong range is undefined behaviour with no
diagnostic. Both emit the same instruction; only one of them checked.

---

## Componentization cost — slides 30 and 31

*gpio 502 → 1196 · timer 204 → 828 · spi 454 → 1450 · wdg 638 → 1718 B. And
1746 → 1428 B, −318, with a bounded arena.*

**What it does not mean.** The **1746** control is a *rebuild* against the
wit-bindgen fork with the feature off — not the shipped 1718 object. The −318 is
attributable to the feature alone; the version bump between them costs +20 B on
its own. Measuring against the shipped object would have credited the feature with
−298 and been wrong.

**Correction on the record.** The spi figure was **1244** in an earlier draft.
That number appears nowhere in the repository or its history; the measured and
recorded figure is 1450.

---

## What synth actually eats — slide 21 (synth tab)

**Correction on the record.** The synth tab's `in` row used to read *WIT / ABI —
lift · lower*, and did not name the actual input at all. On gale's path synth is
handed **one core module** — `loom.wasm`, `fused.stripped.wasm`, or a `.wat`; every
`build-*.sh` in `benches/gust/` calls `synth compile <core-module>`. It is never
handed a WIT file or a component, and its CLI has no `--wit` flag.

synth *does* carry a WIT parser (`synth-wit`) and a canonical-ABI lift/lower
implementation (`synth-abi`) — but on this pipeline they are not on the path,
because **meld already did the lifting and lowering upstream and erased the
boundary**. Claiming them as synth inputs credited synth with meld's work.

If asked "so what does synth do with WIT?" — on this pipeline, nothing. It is a
core-module compiler here. The Component Model work happens one stage earlier.

---

## 50 rules · 50 Rocq Qed — slide 20 (synth tab)

Say the denominator if asked: 50 *selection* rules proved, against synth's own ISA
model. It is not 50 of all rules in all backends, and the model is ours rather than
an external mechanization.

---

## Things to say before being asked

- **Proofs are gated on pull requests, path-filtered** — Verus, Rocq and Kani run
on push and PR to main for proof-relevant paths. A commit outside those paths
triggers nothing. **Lean runs in no workflow at all.**
- **We have not been audited** by any certification authority. The project says so
in its own posture statement.
- **Bounded model checking is bounded.** If asked for the bound on a specific
property, say you will follow up rather than guess.
Loading