Skip to content

talk: Wasm Research Day 2026 — "Change the Tires, Not the Car" - #150

Merged
avrabe merged 57 commits into
mainfrom
talk/wasm-research-day-2026
Aug 6, 2026
Merged

talk: Wasm Research Day 2026 — "Change the Tires, Not the Car"#150
avrabe merged 57 commits into
mainfrom
talk/wasm-research-day-2026

Conversation

@avrabe

@avrabe avrabe commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Draft on purpose. Per the standing instruction this is committed and pushed but not merged — merging to main triggers deploy.yml and publishes to the site. Opening it as a draft gets ci.yml to exercise the build for the first time without any risk of an accidental merge.

The talk is today. The presentation artifact is the self-contained bundle, not this branch.

What it is

33 talk slides + 4 backup, for a 25-minute slot + 5 min Q&A. 48 commits.

Verified standalone (not just "it builds")

Served from a directory containing nothing but the single file:

check result
external src/href refs 0 — nothing to fetch, no CDN, no network
fetch() calls that would fire 0 — the one fetch is behind window.__CASTS, and the cast is inlined
XMLHttpRequest / Worker / WebSocket 0 / 0 / 0
fonts actually loaded 18 faces, Atkinson Hyperlegible Next + Mono
slides 37 (33 talk + 4 backup)
overflow sweep clean at 1024×768, 1180×820, 1440×900
keyboard nav 1 → 3 → 2 ✓
arch tabs selects the pane and its plain-language line ✓
reload-resume ?fresh=1#34 lands on 34/37, the right backup slide ✓
console only a favicon 404 (browser auto-request; absent under file://)

The reload-resume path matters for a remote talk: if the call drops or the browser reloads, the deck comes back on the slide you were on rather than the title.

Q&A navigation

Hash is read on load but there's no hashchange listener, so typing #34 into the URL bar mid-talk won't jump. The working path to backup slides is the overview (grid button / key), then click the slide. That is tested and works.

Backup slides

#
34 Qualify the checker, not the prover
35 Exactly how far this goes — and no further
36 Every one of these gates was green for the wrong reason
37 Two things building this talk taught us

Companion page

content/talks/wasm-research-day-2026-notes.md — every number in the deck: what it measures, what it does not mean, its source, and the corrections made while building it (the USART 326→254 B figure, the spi 1244→1450 B figure, the 11→5 linear-memory miscount, and the falsified "a compiler with no verifier cannot reach it" claim).

Not for merge today

Merging publishes. Leaving as draft.

avrabe and others added 30 commits August 4, 2026 20:58
A Zola section rendering slides through templates/talk.html — no slide
framework, no CDN, self-hosted Atkinson faces, so the deck presents with the
network unplugged. Nineteen slides across five acts, weighted to the factory
(six slides) rather than the demo, per the "the pipeline is qualified once"
framing the site already carries.

Styles derive from the existing tokens in _variables.scss rather than a deck
theme, so a slide looks like the site.

Touch, because it is presented from an iPad:
- swipe left/right, gated on the gesture being decisively horizontal
  (SWIPE_MIN 45px, 1.4x bias) so scrolling a long evidence block does not
  skip slides; disabled in overview, which is itself a scrolling grid
- on-screen prev/next/overview/fullscreen at Apple's 44pt minimum target,
  quiet on pointer devices, always present on touch
- touch-action: pan-y on slides so iOS does not claim horizontal swipes as
  back-navigation; manipulation on buttons to drop the double-tap zoom delay
- 100dvh, since iOS Safari's 100vh hides the last line under the toolbars
- safe-area insets so the chrome clears the home indicator
- webkitRequestFullscreen fallback — iPad Safari has no unprefixed form
- the hint line says "swipe to move" on a device with no hover

One authoring trap worth recording: a blank line inside a raw-HTML block ends
the block, so markdown resumed INSIDE a <pre> and turned a "# correctness:"
log line into an <h1>. Evidence is now several <pre> blocks in a .stack
rather than one with blank lines in it.

Branch only. Not for merge or deploy before the talk.

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

Overview was unusable on a tablet. Diagnosed rather than guessed: at 1180px
every one of the thumbnails overflowed its clipped box by up to 2x and got cut
mid-line, which is what "overlapping" looked like. Hand-shrinking each element
type was never going to hold as slides were added. Thumbnails are now title
cards — act label, heading, number, everything else suppressed — which cannot
spill, stay legible at any width, and are more useful mid-talk anyway. Verified
at iPad landscape: 0 spilled, 0 overlapping pairs, no slide needs scrolling,
no evidence block overflows horizontally.

The pipeline slide answered "what are the stages" but not "what goes in and
what comes out", which is what the tool sites do well. Rebuilt as a flow with
both sides named per stage, down to `ld` taking the .o plus three native
functions and emitting firmware with no engine in it.

Added the code that was missing, all of it lifted from the repo rather than
written to look plausible: the real mmio interface and wdg-driver world, the
actual compose/fuse/optimize/compile commands, the wdg contract that offers no
stop next to the Kani property that proves no escape from Running, and
shim-mmio.js beside the silicon read32 so the substitution is on one slide.

Calibrated against the published schedule for the event:
- the slot is 25+5, not 30 — merged two overlapping slide pairs, 23 -> 21
- the title is already published; the deck now uses it verbatim
- added an opening slide crediting the four adjacent talks (one of them two
  hours earlier the same day) so the work positions against them instead of
  appearing to ignore them
- moved the verification-scope slide out of the closing act into the factory
  act: it and "no runtime resident" are the two claims this venue has not
  heard, and both now land before minute 20

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
Measured rather than eyeballed. At iPad landscape (1180x820) the deck was
rendering body text at 16.8px and CODE BLOCKS AT 11.6px. That is document
sizing on a slide, and unreadable over a shared screen — which for a remote
talk gets downscaled again on the way to the audience.

The cause was mine: every clamp()'s MAXIMUM was set at web-body values
(1.4rem body, .95rem code), so the text could never grow past ~22px/~15px no
matter how large the display. Raised all fourteen steps of the scale.

  before -> after, at 1180x820
  h1        46 -> 52     lead     20 -> 29
  body      17 -> 25     ledger   14 -> 18
  code      12 -> 18     flow     12 -> 16

Also fixes a specificity bug the measurement exposed: `.slide p` (0,2,0) beat
`.slide__act` and `.slide__cite` (0,1,0), so the act eyebrow and every
citation line had been rendering at FULL BODY SIZE from the first commit —
25px where they should be 15. That is most of why the slides read as cluttered.
Qualified all three as `.slide p.<class>`.

Bigger type means less fits, and that was paid in words rather than by
shrinking back: trimmed the prior-art rows, compressed the three-dies logs to
two lines per die, moved the DMA figure off the tire slide, and folded a
duplicated caption into the honesty note.

Verified at 1180x820: 0 slides overflow, 0 code blocks scroll sideways,
0 overview thumbnails spill.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
TYPE. Measured again after the first pass was still too small. Body text on a
slide should be ~4% of slide height; mine was 3%. Raised sixteen steps of the
scale — at 1180x820 body 25 -> 34px, code 18 -> 26px, h1 52 -> 69px — and paid
for it in words rather than by shrinking back: trimmed prose on ten slides,
cut the six-faces paragraphs to phrases, compressed the three-dies logs to two
lines per die, dropped a redundant closing line on the gates slide.

RECORDING. Slide 5 now has a "run it" button that replays a real asciinema
capture of the dissolve: wasm-tools shows the component's WIT, loom optimizes,
synth lowers to a Cortex-M3 object, then nm and size answer the slide's claim
with `U read32 / U write32` and `text 1726  data 0  bss 0`. Recorded by
actually running it — the wdg-thin driver had to be rebuilt first because the
checked-in target/ wasm was a stale pre-componentization build importing
env::mmio_read32.

Written as a ~90-line player rather than pulling in a library: the capture
contains only SGR colour escapes and newlines (verified — no cursor motion),
so append-only rendering is faithful, not an approximation. Text stays
selectable and crisp at any projection size, the file is 1.7 KB, casts are
fetched once at load so clicking mid-talk never touches the network, and a
missing file disables the button instead of breaking the slide.

Two bugs fixed on the way:
- the terminal <pre> had min-height:0 inside a flex column, so siblings
  squashed it to a few pixels — you saw the first commands and nothing else.
  It now claims its space, and "run it" hides the flow diagram so the
  recording gets the whole slide. It auto-scrolls, ending on the payoff.
- `.slide p` (0,2,0) beat `.slide__act` and `.slide__cite` (0,1,0), so the act
  eyebrow and every citation had rendered at full body size since the first
  commit. Qualified as `.slide p.<class>`.

Playback stops and resets when you leave the slide, so it never runs unseen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
…OS itself

The recording covered only loom -> synth, so it silently skipped the first two
rows of the very slide it sits on. Re-recorded against the real 5-provider
composition, and against the OS rather than a single driver:

  wac compose      5 components  -> 1 component, 20741 B
                                    exports 5 gust:os, imports mmio + taskdisp
  meld fuse        11 memories   -> 1 core module, 9874 B (-52.4%)
  loom optimize
  synth compile                  -> gustos.o
  nm -u                          -> poll-task, read32, write32
  size                           -> text 4812  data 0  bss 0

The whole gust OS as one relocatable object with a three-symbol trusted
surface and zero SRAM. That is a better demonstration than a driver was.

Flow rows re-stated from those measurements rather than from memory: the
slide had claimed "5 linear memories -> one shared memory" where meld
actually reports 11 -> 1 core module at 52% smaller, and the "3 native
functions" claim is now the measured undefined-symbol count, not an estimate.

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

The componentization slide named a +700-1100 B canonical-ABI overhead and left
it there. It now also shows what we did about it: our wit-bindgen fork's
cabi-realloc-extern backs cabi_realloc with a bounded arena that traps instead
of growing, worth -318 B (-18%) on wdg-thin, 29% of that driver's overhead.

Measured today with the version bump controlled for — the fork is at 0.58, and
a naive comparison against the shipped 0.52 would have mis-credited the feature.
The slide says the drivers do not use it yet, because they do not.

Turns a slide that admitted a cost into one that shows the loop closing:
name the cost, patch the tool, measure the result, state what is still undone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
Scanned every slide for anything crossing its padding box, at five viewport
shapes. Two real edge overruns (trailing code comments, 35px and 101px) and,
more importantly, a whole class of failure the earlier per-slide trimming could
never have fixed.

The type was sized in vmin, which tracks min(width, height). On a 16:10 screen
that is the width, so body text landed at 2.9% of slide height; on a 4:3 screen
vmin IS the height and the same rule gave 4.2%. Slide fit is height-bound, so
the denser slides overflowed on 4:3 and 1920x1080 while passing on 1180x820 —
and hand-trimming for one shape re-broke another.

Each size is now capped against vh at ~0.79 of its vmin coefficient, pinning
every aspect to ~3.3% of slide height and letting vmin bind only in portrait,
where height is abundant. One lever (`--fs`) remains for a floor on very short
laptop screens. Long code lines wrap rather than scroll below 900px, so a
tablet held in portrait never hides the end of a line behind a swipe.

Measured after, zero overflowing slides and zero elements crossing an edge:

  1024x768   body 25px   3.3%      1180x820   body 27px   3.3%
  1366x1024  body 34px   3.3%      1920x1080  body 36px   3.3%
  820x1180   body 34px   2.9% (portrait — vmin binds, as intended)

Also dropped the closing line on the gates slide; the pull-quote already says it
and it was the one item still overrunning at every size.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
The factory act described the toolchain as six cube faces, which is an
abstraction. synth's own architecture overview is better: it shows WHERE
evidence enters, block by block, and it is the project's own diagram rather
than one invented for a slide.

Six stages — upstream/untrusted, front, middle, back, per-compilation, out —
with the evidence-producing and evidence-checking blocks tinted and the one
hazard block in amber: trap re-introduction, because hardware is more total
than Wasm. That amber block is the most honest thing in the deck's middle: a
diagram that is all reassurance is not a diagram anyone should believe.

It also closes a loop with the cost slide. The FRONT column carries `cabi
arena bind` — wit-bindgen's dangling realloc import resolved to a defined
function — which is exactly the mechanism measured at -318 B two slides later.

Fitting it took the diagram its own scale, since a diagram is read rather than
declaimed: six columns across 1180px put the block labels at 11px, so it flows
3-across into two rows and the labels land at 18px with 15px sub-labels. Diagram
slides also get a smaller heading and tighter stacking than prose slides.

Verified at 1180x820: 22 slides, none overflowing, nothing crossing an edge.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
Two problems with the first attempt, both real.

READING ORDER. The source diagrams are left-to-right stage columns. Six of them
on a slide put the block labels at 11px, and reflowing 3-across into two rows
destroyed the one thing a pipeline diagram has to convey — which way it goes.
Stages are now ROWS with the stage name in a left gutter: one unambiguous
top-to-bottom order, and every block gets real width. Block labels 19px,
sub-labels 16px (was 11/9).

ONLY SYNTH. The talk is about the whole factory, so the slide carried one
tool's internals. meld, loom and synth each publish an architecture in the same
visual language, so the slide now has a tab per tool and switches instantly —
all three stay in the DOM, nothing fetched.

What that buys is the alignment across them, which is worth more than any one
diagram. Each names one hazard, and they are the same mismatch from three
sides:

  meld   Validates != correct     tool lenient · engine strict · run exact
  loom   Total-operation model    the verifier does not see traps
  synth  Trap re-introduction     hardware is more total than Wasm

loom's note states it plainly: Wasm is partial, and everything on both sides of
it is total. A compiler must put traps back; an optimizer must stop taking them
away. Same mismatch, opposite directions, both silent-wrong.

Verified at 1180x820: all three tabs fit with zero overflow, and no other slide
in the deck overflows either.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
SLIDE 14 asserted a fact channel without ever showing one. It now carries a real
wsc.facts payload, computed from loom's own emitter (loom-core/src/lib.rs
build_wsc_facts_payload) rather than invented — schema v1, one value-range fact,
LEB128, nine bytes total:

  01  schema v1 · 01 one fact · 01 kind=value-range
  03  func_index · 07 value_id · 03 00 ff 0f  body: 0 <= v <= 2047

Nine bytes is the point: the whole proof-carrying channel is smaller than the
sentence describing it. The value_id annotation carries the design argument —
keyed to a VALUE, because an optimizer renumbers everything, and a fact keyed to
a position is still true of something while being asserted about something else.
Added loom's own honest scope: emitter and wire format are done and byte-verified
against the consumer, but the source that would populate it at volume is not
wired, so 232->104 is what the channel does when it carries a fact, not evidence
that we produce many.

SLIDE 15 gave three numbers and no mechanism — and mixed ratio directions, so
1.65x read as an improvement when it is a regression. It now shows the actual
function:

  gust_mix(ch) = clamp(1500 + (ch - 1024), 1000, 2000)

LLVM must emit the clamp because it cannot know ch. The OS primitives above
carry a proven bound, ch in [524,1524], so ch+476 is provably inside [1000,2000],
both clamp branches are dead, and the function collapses to `add r0,#476; bx lr`.
Ratios are now stated in words — 1.4x SLOWER today, 2.2x FASTER with the proof —
against a stated unit, so the direction cannot be misread.

That is the whole thesis in one function: not out-optimizing LLVM, but optimizing
with information LLVM structurally never had.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
CONTROLS — my bug, and a bad one for a presenter. The nav was dimmed to .35
opacity under `@media (hover: hover)` and restored on hover. An iPad with a
keyboard or trackpad attached MATCHES that query while the person is still
touching the screen, so the controls faded to near-invisible with no hover
available to bring them back. They are now always visible (.8, full on
hover/focus). A presenter always needs the controls; a little visual noise is
the correct trade.

SPLIT — 22 -> 29 slides. Six slides were carrying two ideas each:

  the pipeline flow          | running it
  the wdg contract           | the proof that the transition is impossible
  the wsc.facts bytes        | why a value and not a position | what it is worth
  the clamp-elision example  | the measured numbers
  the componentization cost  | the patch that recovers 29% of it
  the browser shim           | the silicon side

Each half now gets a slide. Measured after: average fill 62% of available
height (was crowding 100% on the worst), nothing overflows, densest slide 82%.

29 slides against a 25-minute slot is ~52s each, which suits slides that carry
one idea rather than three.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
…eds no server

FONT BUG, and very likely the "works in Safari, not Edge" report. `_fonts.scss`
self-hosts the Atkinson faces, but it was never imported into main.scss — zero
@font-face rules in the compiled CSS. The site got away with it because
base.html also links Google Fonts; the deck template does not, so it silently
fell back to system fonts: SF Pro on Safari/macOS, Segoe UI on Edge/Windows.
Same HTML, different metrics, different look. Importing it gives 18 @font-face
rules and the deck now actually renders in the face it was designed for — the
same one on every browser.

It also closes the privacy regression `_fonts.scss` exists to prevent: the file
says in its own comment that self-hosting eliminates the Google Fonts auto-load
that transmits visitor IPs, and that elimination had never taken effect.

SINGLE-FILE EXPORT (tools/bundle-talk.py). A presentation should not depend on
a working local server, on the browser not upgrading a plain-HTTP LAN address to
HTTPS, or on anything between the laptop and the screen. The bundler inlines the
stylesheet, all 18 fonts as data URIs, and the terminal recording, producing one
632 KB HTML file with ZERO external or absolute references that opens from disk,
offline, in any browser. The player prefers an inlined recording over a fetch,
which fetch() would refuse on file:// anyway.

DRONE SLIDE. Pays off the forward reference on the bias slide. A drone is a car
with four rotors instead of four tires: the flight stack and the building
supervision system are built from the same ten no_std stream-transformer crates,
the same WIT packages, the same component rules, the same traceability gate. And
stated at the same resolution as the claim — neither has flown, neither has
shipped to a home, and the flight dossier says so itself: "no claim of flight is
made anywhere." Aim, not result.

30 slides, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
Ran the deck past six reviewer personas built from the venue's own programme
plus three domain reviewers (military avionics DAL-A, automotive ASIL-D,
robotics real-time). Five reported. Every claim below was checked against the
repo before changing anything.

CORRECTED — overclaims, in the deck's own honesty terms:

- `irq` was listed under "what touches metal" beside dma/uart, which reads as
  interrupt support. The WIT is `poll: func(line: u32) -> bool` — no handler
  registration, no vector ownership, no ISR path. Now says so on the slide.
  Flagged as the deck's most misleading square centimetre, by omission.
- "WCET sidecar / sound per-function" — the sidecar reports 9 DECLINED against
  4 bounded, declines on any call (intra-procedural), and assumes zero-wait-state
  instruction memory, while the same slide lists M7/A53 backends where that
  assumption is fiction. Now "leaf functions only · declines on call".
- "The pipeline is qualified once; every product that uses it inherits that
  qualification" — categorically false under DO-330 and ISO 26262-8. Credit is
  granted per project against user-written tool operational requirements; data
  is reusable, credit is not inherited. Now "qualify once, and the ARGUMENT
  amortizes", which is true and loses nothing.
- 1.839x was tinted green. It is an 84% slowdown. Now amber, and says "slower".
- "0 SRAM" on the fused OS -> ".bss 0". Zero .bss is the real and strong claim;
  "no RAM" is not, and the first question about task stacks collects the slide.
- The `+ wsc.facts` arrow was drawn as populated while a later slide admits the
  producer is not wired. The pipeline slide now says so where the arrow is.
- Two wdg baselines on adjacent slides (1726 B vs 1746 B) were different builds
  presented without explanation. Labelled.
- Added the line the driver-cost slide was missing: flash is cheap on these
  parts, SRAM is the binding constraint, and .data/.bss stay 0 -> 0.

REJECTED — one reviewer claim did not survive checking. The avionics persona
said synth has no WCET support and the deck should delete the chip. But
emit-wcet.sh documents `--emit-wcet`, schema synth-wcet-v1, synth >= 0.46.0
(synth#778); their checkout predates it. Their SUBSTANTIVE point — that the
bound is intra-procedural and model-relative — is correct and is what the
reworded chip now says.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
…e gates exist

The site's own tagline is "AI writes the code. Who proves it's safe?" and the
deck never said it. The entire factory — oracle gates, per-compilation
validation, typed traceability, the five green-for-the-wrong-reason findings —
exists BECAUSE an assistant will produce a plausible driver, a plausible proof
and a plausible green test faster than anyone can read them. Omitting that left
Act IV looking like unusual diligence rather than a necessary response.

New slide before the factory quote: the premise stated plainly, and the pivot
that follows from it — the question stopped being "can it write the code" and
became "what would have to be true for me to believe it." It also sets up the
failure slides as the interesting part rather than as an apology.

Also disambiguates the two wdg baselines (1746 vs 1726) on the slide itself.
Three separate reviewers pulled that thread, and in a deck whose title slide
promises "every number says where it came from", a 20-byte unexplained
discrepancy is the one loose end that unravels the rest.

31 slides, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
As slide 4 it was a claim, and an industrial reviewer's verdict was that it
"spends credibility to buy nothing" that early: an audience hears two unshipped
verticals before it has been given a reason to believe anything. As the
penultimate slide it is an outlook, which is what it actually is — and the
honesty stops being a retraction and becomes a destination.

Retitled "Where all of this is aimed", and the not-yets are now a ledger rather
than a caveat buried in a caption: has not flown, has not shipped to a home, the
board is on the bench and not in the air. Adds what the earlier version omitted
— the hardware-integration hub exists, pins its input by hash, and runs the whole
meld -> loom -> synth chain per upstream release. That is the concrete thing the
substrate is aimed at, and it is the strongest supporting evidence for the claim
the slide makes.

Its dossier's own sentence closes it: "no claim of flight is made anywhere."
Everything earlier in the talk is work toward this, and none of it is this yet.

Act I's forward reference now says "I will come back to that", and it does.

31 slides, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
…he LLVM point

FALSIFIED OUR OWN CLAIM. The deck said "a compiler with no verifier cannot reach
it." Measured: told the premise via core::hint::assert_unchecked, stock LLVM
folds the clamp identically (30 B -> 12 B, add.w r0,r0,#476). The claim is gone.

What replaced it is stronger, and it is the question the whole deck is about:
assert_unchecked is UNCHECKED. You can tell a compiler anything and it will
believe you; get the range wrong and it is undefined behaviour, silently, with no
diagnostic. So both paths emit the same instruction and only one of them checked.
The result was never the codegen — it is the provenance of the premise. "How
would you know the premise is true" is the same question as "what would have to
be true for me to believe it", which is now the deck's stated premise slide.

ADDED — what you still have to trust. Four of six reviewers independently
reconstructed a trusted base because the deck had none, and ".o + 3 native
functions" invites the misread that the TCB is three functions. It now lists what
the gates do not cover, and says outright: three native functions is the seam,
not the trusted base.

ADDED — when NOT to dissolve. The line where a shared system-interface binary is
the right answer instead: several runtimes per OS+ISA, wide dynamic interfaces,
third-party binaries, field update without re-qualifying the image. Naming the
opposing position as correct on its own side of the line is worth more than
arguing against it.

CUT — "Six faces, not four tools" (a product tour of ten proper nouns this
audience does not know; the architecture slide carries the real content) and the
self-quotation slide (a full slide citing our own blog as authority, in a deck
whose entire strategy is evidence). The qualify-once sentence survives on the
premise slide where it belongs.

FIXED — the mixer slide now says the output clamp stays and the bound comes from
a verified primitive rather than off the wire. Two reviewers read the old version
as deleting a failsafe on untrusted input.

31 slides, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
Tried it as slide 4 (read as an unshipped claim before the audience had reason to
believe anything) and then as the penultimate north star. It does not earn its
place either way: the substrate's cross-domain reach is a supply-chain claim about
shared crates, and the talk never needed it to make its argument. An industrial
reviewer's verdict on the early version was that it "spends credibility to buy
nothing", and moving it did not change what it bought.

Also removes the forward reference it left behind: the bias line now stands on its
own, which is stronger — declaring the automotive bias needs no follow-up promise.

The deck now closes: two things building this talk taught us -> before the rest of
the vision holds -> when not to dissolve -> change the tires, not the car. Ending
on where NOT to use this, immediately before the title line, is a better last
impression than an unshipped vertical.

30 slides, none overflowing, ~50s each against the 25-minute slot.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
…y lands

The bias line sat on slide 3, under a split about portability layers, where it
was orphaned from the thing it explains. But the title IS the metaphor — the
moment "Change the Tires, Not the Car" is on screen, a room of compiler and
formal-methods people is already holding the "why cars?" question. Answering it
two slides later means they sat with it through the prior-art slide.

On the title it also pairs with the other declaration already there: the bias and
"every number on these slides says where it came from" are the same kind of
statement — here is my position, and here is how to check me. Two declarations,
one slide, before any claim is made.

30 slides, none overflowing.

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

Wrote the deck's factual claims as 40 falsifiable statements and had them checked
by a verifier briefed cold, told to measure rather than trust any document's
assertion about itself, and told that cannot-verify beats a guess. Six refutes.
Five stand; four were mine, introduced in this session.

REFUTED AND FIXED:

- "11 linear memories" -> 5. My own count: I grepped `(memory ` and hit 5
  declarations plus 5 `(export "memory"` lines plus one `canon lift (memory $m)`.
  meld's stdout says "Fusing 11 components", which made the wrong number look
  right. FUSED-GUSTOS.md says plainly "Linear memories: still five".
- spi 454 -> 1244 B. Refuted: 1244 appears NOWHERE in the repo or its history.
  The measured and recorded figure is 1450 (spi-thin/RESULTS.md:71, and a rebuild
  agrees).
- wdg 638 -> 1726 B. The committed componentized object is 1718; 1726 is only
  reproducible as a synth-0.49 rebuild. Cost slide now uses the shipped 1718, and
  the patch slide says its control is a rebuild rather than the shipped object.
- USART driver 326 B -> 254 B. The committed uart-thin-cm3.o measures 254/0/0.
  326 comes from RESULTS.md attributed to loom 1.1.16 + synth 0.15.0, a toolchain
  two years stale; no build reproduces it today.
- `add r0,#476; bx lr` as "the whole function". The measured codegen is five
  instructions and 12 bytes, including uxth and a frame push/pop. COMPARE.md
  labels the two-instruction form "what synth COULD ship (synth#494a)" — an
  aspiration I had put on a slide as a measurement.

REFUTE REJECTED: the verifier found no "we have not been audited" statement and
refuted it. It searched gale; the sentence is on the website
(templates/about.html:58 and :89, "We will tell you when an authority audit
happens; we have not been audited yet"). Claim stands.

ALSO CORRECTED, in our favour: "Proofs run on a schedule, not every commit" was
wrong in the pessimistic direction. Verus, Rocq and Kani ARE gated on push and
pull request to main — path-filtered, so a commit outside those paths triggers
nothing. The real gap is narrower and sharper: Lean runs in no workflow at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
It said "OS written for the chip. Application hoped to be portable. Every new
board re-opens the OS." — a caricature, and weak precisely where the argument
needs to be strong. An audience with embedded experience hears a caricature and
discounts everything after it.

Retitled "How embedded actually builds software", and now says what, why and how:

  WHAT — the vendor's HAL and board-support package for that part; an RTOS with a
  port layer per architecture and a board file per board; register headers
  generated from the chip's own description file; #ifdef for variants; one
  statically linked image.

  WHY — and it is the right answer. No MMU. Kilobytes of RAM. Hard deadlines.
  Cents per unit. Every abstraction costs bytes and cycles that are not there,
  and the vendor knows the silicon better than you do. It works.

Then the consequence, which is the only part actually worth arguing about: the OS
is the layer that gets rewritten per target, and the application's portability is
a convention rather than a contract.

Conceding that the incumbent is correct under its constraints is what earns the
right to propose a different one — and it makes the inversion a response to a
real cost rather than a claim that everyone else was doing it wrong.

No vendor or product names, per the standing rule; all of it stated generically
and factually.

30 slides, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
Walked all 30 asking one question per slide: does this carry enough to explain
what it is, or to set up the thing it demonstrates? Six could not.

- 6 "The same chain, actually run" was a heading and a button — twelve words. If
  the recording is not played, or it fails, the slide says nothing at all. It now
  states what you are about to watch and, more importantly, the two questions the
  run answers: what does the object still need from the world, and what does it
  cost.
- 8 showed `interface wdg { unlock · configure · lock ... }` — names separated by
  dots. That is prose in a code box, and in a room full of Component Model people
  it discounts the entire contract argument. Replaced with the real WIT, six
  function signatures, verbatim from gust-hal.wit.
- 12 opened on JavaScript with no framing. It now says what the shim IS — the
  answer to an imported interface — before showing it.
- 19 said "a bounds-guard sequence", which is unfalsifiable as written. Now "one
  guarded memory access, lowered with and without the fact".
- 22 gave "62 / 62" with no denominator, which is a ratio chosen to be 1.0. Now
  carries its own scope row: 62 of the BIT-VECTOR obligations, and the rest of
  each proof still rests on the solver.
- 24 listed five verification failures in five cryptic lines and explained none.
  One is now worked through concretely — a requirement said the fuser rejects a
  component that instantiates a module twice; the test called the reject function
  directly and passed; the shipped path accepted those modules and duplicated
  them. That is the one that generalises, and it is what makes the pull-quote land.

30 slides, none overflowing, nothing crossing an edge.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
Rows like "2022 | lowered ahead of time, no engine | x86-64" named no work and no
group, so they read as "prior art exists, in the abstract" — and the right-hand
column silently reduced each prior result to its deficiency relative to this one.
Two reviewers said an unattributed year-row is worse than no row. Fixing it meant
naming four talks, which brushes the standing rule on third-party names in public
artifacts, for a slide that was not carrying its 50 seconds.

Cut rather than repaired. Crediting the adjacent work verbally costs nothing, is
more generous than a ledger row, and can name the delta properly — which is the
part that was wrong anyway: the interesting difference was never the instruction
set.

Nothing depended on it — checked for references to "four ingredients", "all four
at once", "two hours ago" and the named analysis; zero hits.

29 slides, none overflowing, ~52s each. Act I is now a single slide, which suits
it: the inversion is one idea and the deck gets to the seams faster.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
Each tool publishes its architecture with its own stage vocabulary — meld says
Parse/Resolve/Merge/Adapt/Out, loom says In/IR/Passes/Per-compilation/Gate/Out,
synth says Upstream/Front/Middle/Back/Per-compilation/Out, scry says
In/Value-domains/Relational/Memory/Fixpoint/Out. Four names for the same five
things, which made the slide look like four unrelated tools.

They are now one spine — in · model · work · check · out — identical rows in all
four tabs, so switching tools compares like with like instead of asking the room
to re-learn a vocabulary three times.

scry added as the fourth: verified premises in, ten abstract domains as the model,
the fixpoint as the work, 19 Rocq files with 0 admits as the check, and out the
shadow-stack bound that synth consumes plus a gap report of every ⊤ as data.

The unification pays off in the hazard row, which is the real result. All four
name exactly one hazard, and it is the SAME defect four times — each tool's model
is more total than Wasm:

  scry   wrapping arithmetic     Z is not i32
  loom   total-operation model   the verifier does not see traps
  synth  trap re-introduction    hardware is more total than Wasm
  meld   validates != correct    the validator is lenient where the machine is exact

Wasm is partial; mathematics, SMT, silicon and validators are all total. That is
a property of the specification's neighbours rather than of any one tool, and it
is worth more than any single diagram on the slide.

Verified: identical five row labels across all four tabs, one hazard each, zero
overflow on every tab. 29 slides.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
The tabs read meld / loom / synth / scry — four names this room has no reason to
know — and the rows below them are structure, not purpose. The slide said HOW
four times and never once said WHAT. Selecting a tab now swaps a plain-language
line in above the diagram:

  meld   welds many components, joined at their interfaces, into a single
         module — so the boundaries stop existing at run time
  loom   rewrites the code to be smaller and faster, and reverts any rewrite it
         cannot prove keeps the same behaviour
  synth  turns the wasm into real machine instructions for a real chip, and
         re-proves the translation on every compilation
  scry   reads the code without running it and works out what can and cannot
         happen — recording every place it had to give up

Each is the tool's actual contract in one sentence, and each carries the thing
that makes it unusual: loom REVERTS what it cannot prove, synth re-proves PER
COMPILATION, scry records where it GAVE UP, meld makes the boundary stop
existing. Someone who reads only these four lines has the talk's argument.

Verified per tab: exactly one description and one row-set visible, both matching
the selected tool, zero overflow on all four. 29 slides.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
…ing the incumbent

The old Act I slide was a split: "the usual arrangement" beside "what we are
trying". Rewriting it into the traditional-embedded steelman replaced BOTH
columns, so the second one — the actual proposal — was silently dropped. The deck
then went from "here is how embedded builds software today, and it is the right
answer" straight into WIT interface listings, with the thesis missing from
between them. Caught on a read-through, not by any check I had.

New slide 3, "So invert it": write the OS itself as WebAssembly components and
make the Component Model the integration step — between OS components, between
the OS and its drivers, between the OS and the tenants above it. Not a runtime on
the device: a build step that joins typed pieces and then gets compiled away.
Then the car and the tires, which is what the title has been promising since
slide 1 and which nothing had yet cashed.

It also gives slide 4 something to be the answer to: "two seams, and everything
hangs off them" only means something once the room knows the OS is supposed to be
made of components.

30 slides, none overflowing, ~50s each. Act I is two slides: what everyone does,
and what we do instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
The pipeline read `wac compose · meld fuse · loom optimize · synth compile · ld`.
Those names mean nothing to this room, and the slide that explains them is 16 —
eleven slides after the one that depends on them. The audience was being asked to
follow a chain of four unfamiliar proper nouns before being told what any of them
do.

The stage column now leads with the ACTION and demotes the tool to a sub-label:

  compose (wac) -> fuse (meld) -> optimize (loom) -> lower to ARM (synth) -> link (ld)

Anyone can follow compose, fuse, optimize, lower, link. The names are still there
for whoever wants to go and find them afterwards, which is the only thing they
were ever needed for on this slide.

Added the sentence the slide was missing: five components in, one native object
out, and every arrow happens on a build machine rather than on the device. That
is the whole claim of the slide title, and it was only implied by the diagram.

30 slides, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
The verb/tool split shipped with markup but no style: the sass edit that was
supposed to add `.flow__stage small { display: block }` silently matched nothing,
because an earlier pass had already rewritten that block's font-size to the
vh-capped form. String replace found no match, wrote the file unchanged, and
reported success — so `<small>wac</small>` rendered inline and the stage read
"composewac".

I checked the markup and the measured slide fit afterwards, and both were fine.
Neither of those could see the defect: the element was present, the slide did not
overflow, and textContent concatenates without whitespace anyway, so my own
verification printed "composewac" and I read it as expected output rather than as
the bug.

Rule now applied against the block as it actually exists, and verified where it
matters — computed display is `block` on all five, and each tool name measures on
its own line beneath its verb:

  compose (wac) · fuse (meld) · optimize (loom) · lower to ARM (synth) · link (ld)

30 slides, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
New slide, "The part sets the rules", right before the seam. It carries the
geometry (128K flash / 8K SRAM, generated from the AADL model rather than
hand-written) and then the number the deck was missing entirely: a whole flashed
image on that part is 6 028 B of flash and EIGHT BYTES of SRAM, leaving 8 184
free.

This reframes the rest of the deck. "0 SRAM drivers", "no engine", scalar-only
interfaces and an allocator that traps instead of growing all read as taste until
the audience knows the part has 8 KB — after which they read as consequences.
Three reviewers reached for this independently: the automotive one said the
componentization tax is fatal exactly on this part class and noted our demo dies
ARE that class; the industrial one said zero static RAM is the number that
matters and it was sitting on a slide titled "what componentizing costs" as the
consolation prize.

Scope on the slide and in the repo note: this is the watchdog silicon test image,
one dissolved driver plus the minimum to boot and report — a floor, not a system
footprint, with no scheduler, task set or application in it.

31 slides, none overflowing, ~48s each.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
…st board we had

I had framed the F100 as "the part that sets the rules" — true, but it read as a
size stunt. It is the FAILSAFE: the IO-MCU beside the main flight computer,
forwarding per-motor commands. If that computer stops, this is what is still
driving the motors.

And its safety property came from a real failure. It must forward commands
BYTE-EXACT — no re-mixing, no per-motor floors — because when a rotor fails and
the controller asymmetrically zeros motors, re-mixing reintroduces the parasitic
moment that caused a real failure in a prior release. The oracle is 184 checks,
46 rows x 4 motors, byte-exact, with a negative control that MUST fail: a
symmetric averaging re-mix has to be rejected.

That changes what every constraint in the deck means. "0 SRAM drivers", "no
engine", scalar-only interfaces, an allocator that traps rather than grows — all
of it read as taste when the part was anonymous. Attached to a controller whose
job is to keep an aircraft flying after a motor dies, they read as consequences.

Split into two slides because the two ideas are separable and each is a full
thought: what the part IS and what its property is, then what an image costs on
it (6 028 B flash, 8 B SRAM, 8 184 free), with the scope stated — one dissolved
driver plus the minimum to boot, a floor and not a system footprint.

32 slides, none overflowing, ~47s each.

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

The slide asserted the pass-through property as prose, which in a deck arguing
that traceability is the point was the wrong way round. It is defined as a typed
requirement: the three-core partition (flight cascade on the M7, estimator on the
M4, failsafe on the F100), PART-P02(a) pass-through fidelity, its WIT generated
from the architecture model rather than hand-written, and an oracle gating it —
46 rows x 4 motors, byte-exact, with a negative control that must fail.

That is the factory applied to the car, and it closes a loop the deck had left
open: Act II shows the artifact, Act IV shows the machinery, and until now
nothing said the machinery had produced this particular artifact.

Status stated on the slide: DRAFT. The requirement is specified against a future
release, not delivered — and in a deck whose title slide promises every number
says where it came from, a specified-but-undelivered requirement has to say so
where it is claimed, not in a backup slide.

32 slides, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
avrabe and others added 27 commits August 5, 2026 00:00
…our word

Checked what the toolchain actually claims. gale's OS-node builds pass
`synth --shadow-stack-size 2048`, and synth's own flag contract says exactly what
that means: "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
(that is the layer-2 auto-proof / scry tail)."

So on a part with 8 192 bytes of SRAM we reserve 2 048 of them on an assertion,
and the deck did not say so — while spending two slides on how little SRAM the
drivers use. That is the wrong side of the ledger to be quiet about.

The gaps slide now names it: an OS node reserves 2 048 of those 8 192 bytes, the
compiler's contract says the budget is asserted rather than proven, scry computes
the depth, and wiring it to the reservation is the named next step. Until it
lands, the number is our word.

This is also the specific answer to a reviewer's "no stack bound, no ASIL-D" —
the honest position is not that we have the bound, it is that we know exactly
which tool produces it and exactly what is missing between here and there.

Noted while checking, not put on a slide: synth ships `--stack-layout low`, which
places the stack at the bottom of SRAM so an overflow BusFaults on the first
errant push instead of silently corrupting globals — no MPU needed. It refuses on
relocatable, host-linked images, which is precisely our path, so the harness owns
that layout and we do not get the protection. Worth a look separately.

32 slides, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
Asked whether slide 23 should mention the assert_unchecked result. Checked: it
was not on 23, it was not on 22, it was not in the deck at all. Splitting the
clamp slide into mechanism + numbers dropped it, exactly as splitting the Act I
slide dropped the inversion column earlier today. Third time a string-replace
edit has silently lost content in this session, and this time it took the single
best line in the deck.

Restored as its own slide, which is where it belonged anyway — the objection
forms the instant the numbers table claims 2.2x against native LLVM, so it should
land on the very next slide rather than be folded into either neighbour:

  assert_unchecked(524 <= ch && ch <= 1524);
    -> add.w r0, r0, #476     stock LLVM, 30 B -> 12 B

  "So the codegen is not the result. Both emit the same instruction — only one of
   them checked."

  "You can tell a compiler anything and it will believe you. Get that range wrong
   and it is undefined behaviour, silently, with no diagnostic. The question was
   never CAN the compiler fold it — it is HOW WOULD YOU KNOW the premise is true."

Verified by rendering rather than by grep: the source greps as zero for
"assert_unchecked" because the markup splits the token, which is precisely the
kind of false negative that let it go missing in the first place. Confirmed
present in the rendered DOM, on slide 24, with no overflow.

33 slides, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
HIGHLIGHTING. Eight source blocks now carry data-lang (wit, rust, js, sh) and get
tokenised. Captured output, hexdumps and measurement tables deliberately do NOT —
colouring evidence like code misrepresents what it is.

The highlighter rewrites only the DIRECT text-node children of a tagged block, so
the hand-authored spans marking results (.ok/.dim/.hi) are never touched or
nested into. First version ran its rules in sequence over a string that was
accumulating markup, so `str` inside `class="tok-str"` matched the Rust type list
and corrupted two blocks into `class="tok-ty">Uint32Array`. Rewritten as a single
non-rescanning tokenizer pass with keyword sets. Verified: 0 corrupted blocks,
0 untagged blocks touched, manual spans intact.

DMA RESTORED. A history sweep for content silently lost to my slide edits found
exactly one real casualty — the DMA ownership figures — and it left `dma` as a
bare unexplained word in the gust:hal list, which is what prompted the question.
It is back, and it is the strongest Component Model content in the project:

  resource dma-buffer { len: func() -> u32; }
  read: func(channel: u32, buf: dma-buffer) -> future<dma-buffer>

Consuming own<dma-buffer> makes the buffer statically inaccessible to wasm until
the future resolves with the re-owned handle; circular DMA is a stream of
per-chunk ownership, each chunk owned by exactly one side at a time. 220 B,
0 SRAM, 6 Kani proofs.

That block uses resource, own, future AND stream — the exact question a Component
Model audience asks about a deck whose every other interface is scalar. Corrected
against the artifact while restoring it: the object is 220 B, not the 218 I had
been carrying.

34 slides, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
…th no source

Slide 20 opened "When loom proves a value range it does not discard it" and never
said how loom knew the range. A room that has just been told to distrust every
stage will ask, and the honest answer is better than the omission:

  "It is not running a separate pass to hunt for facts. To delete a bounds check
   it must already have established the index is in range — every optimizer does
   that. What is unusual is what happens next: normally the code is emitted and
   the reasoning that justified it evaporates."

That reframes the contribution. It is not extra analysis bolted on for our
benefit; it is declining to throw away work the optimizer already had to do to
justify its own rewrite. Which is also why the cost of the channel is nine bytes
rather than another analysis pass.

34 slides, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
…esented today

Our upstream analyser and the bounds-check work presented earlier the same
morning are the same family of technique on the same problem. Saying so is the
strongest move available, because the comparison is unflattering in the places
that matter and admitting that is what makes the rest credible: their output
contract is cleaner (a flat list of provably-safe offsets any runtime can
consume), they handle a branch shape ours misses, and they measured an end-to-end
speedup we have not.

And it turns the deck's biggest admitted gap into an ask. The previous slide
concedes that the source which would populate the fact channel at volume is not
wired. That analysis produces exactly those facts. Both projects are about two
months old.

Better than a prior-art ledger row: it credits by contribution rather than by
year, names what they do better, and ends in a collaboration rather than a
comparison.

NOT added, because it is not true: a claim that we implemented RFC-46. Asked
whether to mention it, checked, and meld's own RFC response says "On
multiply-instantiated modules: we currently reject these" — corroborated by
commit 2137398, "already mitigated by reject", and by the absence of any
implementation in the crates. What exists is a considered response from an
independent implementer, offering 45 canonical-ABI fixtures, edge cases found
through debugging, and Rocq proofs as a reference specification. That is worth
saying out loud in Q&A; "we implemented the RFC" is not.

35 slides, none overflowing, ~43s each.

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

I said we had not implemented RFC 46. That was wrong, and it was wrong in the way
this deck is about: I read one section — "on multiply-instantiated modules: we
currently reject these" — and generalised a local negative into a global one
without reading the rest.

The response's own opening says meld "does essentially what this RFC proposes for
the sync subset of the component model", and that "the core architecture matches
what this RFC describes: parse components, flatten the composition DAG, merge
index spaces, generate FACT-style adapter trampolines, wrap the result back into
a P2 component for host compatibility." Multiply-instantiated modules is one
question inside the RFC, not the RFC.

New slide, "Is this the Component Model, or our dialect?", which is the question a
CG audience asks first and the deck had no answer to:

  43 / 45   canonical-ABI fixtures pass at runtime — strings, lists, records,
            variants, options, results, resources, flags, enums, both directions
  declined  async / fibers — no stack switching on these parts, and compiling the
            runtime in is a TCB problem
  rejected  multiply-instantiated modules — refused rather than shipped as an
            unproved transform

with the two known failures named: three-component resource chains where an
intermediate re-exports a resource it does not define.

That is a far better answer than either "we follow the spec" or my previous "we
did not implement it" — it is a conformance ledger, with the declines stated as
choices and the rejection stated as a refusal to ship something unproven.

36 slides, none overflowing, ~42s each.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
With tool names running through the deck, "is this slide about meld specifically,
or about everything?" was a question the audience had to hold while also
following the argument. Each slide now carries a scope chip beside its act label,
coloured by kind: accent for a single tool or component, cyan for a set or the
whole chain.

  the whole chain · four tools · five tools · loom -> synth · synth vs LLVM
  meld · scry · synth · the checker · wit-bindgen
  gust:os · gust:hal · gust:hal · dma · gust on the F100 · one driver
  gust, three parts · gust, three hosts · gust drivers
  everything below the seam · all of it

29 tagged. Seven deliberately not: the title, the two Act I framing slides, the
AI premise, the two-things-we-learned slide, when-not-to-dissolve and the close.
None of those is about a tool, and a chip there would be noise pretending to be
structure.

The distinction it draws is the one that actually matters for this deck: a claim
about one component is a different kind of claim from one about the pipeline, and
several of the numbers only mean what they mean at a stated scope — "43/45" is
meld, "8 B of SRAM" is one image on one part, "four tools, one spine" is the set.

36 slides, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
Removed: qualify-the-checker (LRAT/Lean/62-of-62), the verification-scope ledger
(including "we have not been audited"), the five green-for-the-wrong-reason
findings, and the two-things-building-this-talk learnings.

That is the entire software-process spine, and cutting it is right for THIS room.
Wasm Research Day is co-located with the CG meeting; its currency is results
about WebAssembly, not lessons about how a team verifies its work. Those four
slides answered questions nobody at this venue asked — "we have not been audited"
matters to a certification audience, and "check whether your gate can go red"
belongs at a verification-practice venue. Both are true and neither is a wasm
result.

The test applied was a good one: could this be explained quickly to someone
outside the field, and can it be justified at this venue. All four failed both.

What it costs, stated plainly: six reviewer personas independently called the
green-for-the-wrong-reason slide the best in the deck, and one called it a
publishable negative result. It is genuinely strong material — for a different
audience, in a different talk. Keeping it as a Q&A answer costs nothing; keeping
it on a slide cost four minutes of a twenty-five minute wasm slot.

What it buys: Act IV is now the fact channel, the architecture, and the
measurement, end to end — which is the wasm contribution. Checked for dangling
references to the cut material: none.

32 slides, none overflowing, ~47s each.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
THE ASK. The deck ended on a slogan and a URL — memorable, and nothing anyone
could act on or measure. New penultimate slide, "Two things I want from this
room", makes both asks concrete and venue-appropriate:

  the channel is nine bytes and the schema is yours — if your analysis produces
  value ranges, it already produces the facts it carries; mine has an emitter, a
  wire format and a consumer, and no source at volume

  which fragment of the Component Model survives complete ahead-of-time erasure?
  my ledger is 43 of 45, minus async, minus multiple instantiation — tell me
  where it is wrong

Both are observable within days: does anyone ask for the schema, does anyone
engage the erasure question. Neither is "did they find it interesting".

Deliberately NOT the ask: "go and check whether your own gate can go red." That
is a software-process finding and this is a wasm research day co-located with the
CG meeting. True, transferable, wrong venue.

BACKUP. The four slides cut for venue fit are restored after the close, marked
`backup — not in the talk` with an amber rule so the speaker can never wonder
whether they have run past the ending. They are exactly the right backup
material, because each answers a question likely to be asked and none of them
belongs in the linear 25 minutes: the checker/certificate argument, the
verification-scope ledger, the five green-for-the-wrong-reason findings, and the
making-of learnings. Press the overview button and jump straight to one.

33 talk slides (~45s each) + 4 backup. None overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
…her option

"The missing source was in this room this morning" referred to concurrent work
without naming it, because I was applying the no-third-party-names rule to a
research venue where citing adjacent work is the norm. The result was the worst
of both: too specific to be general, too coy to be a credit. It reads as either
not knowing whose work it is, or not wanting to say.

Cut rather than repaired, because the ask slide added a moment ago already
carries the point in its general form — "if your analysis produces value ranges,
it already produces the facts it carries" — and makes the same offer to whoever
in the room it applies to, without the awkwardness.

The specific credit is better said out loud anyway: naming the work, saying what
it does better than ours, and that its output is exactly what our channel lacks,
is more generous spoken than as a bullet — and it lets the comparison be warm
instead of a ledger row.

Checked for dangling references to the cut slide: none.

32 talk slides (~47s each) + 4 backup. None overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
The plain-language line said scry "reads the code without running it and works
out what can and cannot happen". Accurate, and it threw away the one word that
locates the tool instantly for this audience. A wasm research room co-located
with the CG meeting does not need abstract interpretation explained; it needs to
be told that is what this is.

  "scry is SOUND ABSTRACT INTERPRETATION — it reads the code without running it
   and over-approximates, so what it proves holds on every run. It records every
   place it had to give up as data."

Naming the technique also does work the deck lost when the unnamed-credit slide
was cut: it puts scry in the same family as the bounds-check work presented
earlier the same day, so the verbal credit has something on screen to attach to,
and the over-approximation clause says why its output is safe for a consumer to
act on.

Verified on the tab: line swaps correctly, zero overflow on all four tabs.

32 talk slides + 4 backup, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
…ime to transact

"Two things I want from this room" was an ask, and the slot has five minutes of
Q&A. There is no room to transact, and after twenty-five minutes of being taken
somewhere an audience should leave holding something, not owing something.

Reframed as "Three things to take with you":

  one    the Component Model can be a BUILD step — it does not have to be present
         at run time; 43 of 45 canonical-ABI fixtures survive complete erasure
  two    a proof can cross a tool boundary in NINE BYTES — keyed to a value,
         dropped rather than re-pointed when the value dies
  three  on a part with 8 KB of RAM the seam costs nothing at run time, because
         by then it is not there

Each is a result the room can check, and each is the payoff of a leg of the
journey: the erasure profile from the meld ledger, the channel from Act IV, the
footprint from the failsafe part.

The ask survives as one line underneath, as an invitation rather than a request:
the schema is open, and the erasure ledger is a claim rather than a result — if
it is wrong I would rather hear it than not. That still produces the measurable
outcome (does anyone ask for the schema, does anyone contest the ledger) without
spending the closing slide demanding it.

32 talk slides + 4 backup, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
New slide 2, "In twenty-five minutes" — by the end you will be able to:

  say which parts of the Component Model survive being compiled away entirely,
  and which do not
  describe how one tool hands a machine-checked fact to the next, and why it is
  keyed to a value rather than a position
  quote what an operating system made of components costs on a part with 8 KB
  of RAM

Deliberately the same three as the closing slide, in the same order. The audience
decides in the first minute whether to spend attention, and a concrete promise is
what buys it — then the close pays exactly that promise back rather than
summarising whatever happened to be said.

It also gives the middle a spine: every act now visibly serves one of the three,
which is a better test for future cuts than "is this interesting".

Closing line makes the contract explicit rather than implied: if any of those is
still unclear at the end, I have failed — ask me. In a five-minute Q&A that also
does useful work, by telling the room what a good question looks like.

33 talk slides (~45s each) + 4 backup, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
Thirty-three slides and no author anywhere — an omission nobody had caught,
including six reviewer personas and a clean-room verifier, because every check
was aimed at whether the claims were true rather than at whether anyone could
tell whose claims they were.

Title slide now carries "Ralf Anton Beier · avrabe" between the subtitle and the
declarations, and the closing slide carries the same plus github.com/avrabe.
Both names on purpose: the full name is who is speaking, and at this venue the
handle is what someone actually types afterwards to find the work. A talk that
successfully persuades a room and then leaves them unable to locate the repo has
wasted the persuasion.

33 talk slides + 4 backup, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
"say which parts survive" was the odd one out against "describe" and "quote",
and it undersold its own bullet. Explaining which parts survive implies knowing
why they do; saying them implies reciting a list.

The three verbs now escalate, which is what the slide wants: explain the
mechanism, describe the protocol, quote the number.

  explain  which parts of the Component Model survive being compiled away
  describe how one tool hands a machine-checked fact to the next
  quote    what an OS made of components costs on a part with 8 KB of RAM

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

SLIDE 8 said "flight computer" and "rotor" without the deck ever mentioning a
drone, and put two numbers (128K/8K) inside a 1296px-wide code box that was
mostly empty frame. It now opens with the context — we build flight software for
a drone, a car in the air with four rotors instead of four tires, and this is its
emergency motor controller — and the geometry is a single ledger row instead of a
near-empty <pre>.

43/45 — my phrasing on the takeaway slide was loose in two ways, caught on being
asked what it actually means. It said the fixtures "survive complete erasure",
which implies lowering all the way to native with no runtime present, and it read
like a spec-coverage ratio.

What the number is: 45 wit-bindgen fixtures, each a component graph exercising
one canonical-ABI feature — strings, lists, records, variants, options, results,
resources, multi-return, flags, enums, type aliases — in both directions of
cross-component calls. meld fuses each graph into one core module, the fused
module is RUN, and behaviour is compared against the unfused original. 43 behave
identically.

So the row now says what was measured: fuse the graph into one core module and
the boundary is gone, and 43 of 45 canonical-ABI fixtures then behave
identically. The two that do not are named in the footer — resource chains
through a re-exporting middle component. A number a listener can act on beats a
number that sounds bigger.

33 talk slides + 4 backup, none overflowing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
…t mean

The title slide promises "every number on these slides says where it came from".
This writes that down, as a second page to keep open on another screen during
Q&A. Per figure: what the slide says, what it actually measures, what it does NOT
mean, and where it came from.

Covers 43/45 (slides 19 and 32), the composition figures, the 8-byte image, the
2048-byte stack reservation, the driver seams, the three dies, the fact channel,
the clamp numbers, the componentization cost, and the 50 Rocq Qed denominator.

It also carries the corrections made while building the deck, on the record and
in the speaker's own hands rather than only in commit messages:

  11 linear memories was 5 — a grep that also matched export lines
  spi 454 -> 1244 was 1450 — 1244 appears nowhere in the repo
  the USART seam was 326 B, is 254 — 326 came from a two-year-old toolchain
  the DMA object is 220 B, not 218
  "a compiler with no verifier cannot reach it" is false — LLVM folds it too
  the -318 control is a rebuild, not the shipped 1718 object

And a closing section of things to volunteer before being asked: proofs are
gated on PRs but path-filtered, Lean runs in no workflow at all, and we have not
been audited.

The point is that a number a speaker can defend under questioning is worth more
than a number that sounds larger — and the two failing fixtures, the asserted
stack budget and the 1.4x-slower shipping configuration are all easier to say out
loud first than to concede second.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
…ilure's shape

Three corrections the audience would have hit:

synth's `in` row claimed "WIT / ABI — lift · lower" and never named the real
input. Every build script in benches/gust/ calls `synth compile` on a core
module (loom.wasm, fused.stripped.wasm, or .wat); synth's CLI has no --wit flag.
It does carry synth-wit and synth-abi, but they are off this path — meld does the
lifting and lowering one stage earlier. The row credited synth with meld's work.

The cyan/amber coding had no key, and at 8% tint on a cream ground it was not
even visible. Both fixed: stronger tints, and a legend on the closing line
saying what the two colours mean.

"The two" on the ledger now carries the shape of the failure in the value column
rather than a paragraph of prose. The figure had to be allowed to wrap —
.ledger__val sets white-space: nowrap, which it inherited and which clipped it at
iPad width instead of shrinking.

Spacing tightened on 6, 21 and 30 so all 37 slides fit with zero overflow at
1024x768, 1180x820 and 1440x900. 6 and 30 were already over at 4:3 before today.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
…n an outlook

Three changes, all from presenting-day review.

1. The inversion was described as a METHOD ("write the OS as components") when it is
   a CLAIM about how embedded works. Slide 4 now leads with it: in embedded the
   hardware defines the software -- pick the part and you have picked the OS, the
   drivers, the toolchain -- reverse that dependency, so the software is the durable
   artifact and the silicon is a parameter. The car/tires metaphor follows from it
   rather than standing in for it.

2. Exact parts instead of shorthand. "F100" -> STM32F100RB (the VLDISCOVERY part,
   128 KB flash / 8 KB RAM, geometry generated from stm32f100.aadl) and
   NUCLEO-G474RE -> STM32G474RE, so the board and the MCU are not conflated. The
   part is now named on slide 8's geometry row, where the 8 KB claim is made.

3. Slides 30 and 31 replaced by ONE outlook slide: "What we are building next, and
   what would change our minds." The gaps are not dropped -- they become the thing
   being worked on, which is what a research-day room can engage with. Both originals
   move to backup, where the earlier cuts already live, so they remain available in
   Q&A. The outlook is grounded in the actual release plan: dissolve the whole OS
   first (nothing can be verified at object level or bounded until that object
   exists), then the stack bound, then isolation on real MPU regions; and the dissolve
   is still a trusted step. It closes with what would falsify us.

Deck is now 32 talk + 6 backup. Verified zero overflow and zero clipped elements at
1024x768, 1440x900, with slide 21 checked on all four tabs. Bundle rebuilt (651 783 B,
18 fonts inlined, no external refs). Notes page renamed the part to match.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
…ware-defined

Three review points from presenting-day read-through.

1. Slide 12 was carrying an acronym the deck never expands. "FSM" appeared EXACTLY
   ONCE in the whole deck -- in that slide's heading -- and the slide never showed the
   state machine or named its states, so the audience had to take both the acronym and
   the object on faith.

2. Slides 11 and 12 were a pair making one argument, and 11 already carried it
   visually: six functions, no stop. Merged into one slide. The proof survives as the
   sentence that was actually the point -- the driver is a small state machine,
   Idle -> Configured -> Running, and a bounded proof shows no edge leaves Running.
   The Kani harness listing goes to backup, so it is one keystroke away if anyone
   pushes on how the proof is done.

   Deck is 31 talk slides now, down from 33 at the start of the day, on a 25-minute
   slot.

3. Slide 4 names the term. The claim was there but the word was not, so the audience
   had to supply the connection: what software-defined means down here is not features
   pushed over the air onto hardware chosen years ago, but software portable across
   silicon that stays verified across the move. The second half is the part almost
   nobody attempts, and it is what the rest of the deck is evidence for.

Verified: zero clipped elements at 1024x768 and 1440x900, slide 21 on all four tabs,
zero FSM mentions remaining in the talk path. Slide 4 reports a 10 px overflow at 4:3
that is bottom padding, not content -- its last line ends 108 px above the slide edge
and 55 px above the nav, measured.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
It read "... and the FSM proves the absence", which continued slide 11's title before
the merge and now stands alone -- with the one unexplained acronym in the deck. It is
the slide you reach only when someone pushes on how the proof works, so it should read
on its own: "The bounded proof behind that contract".

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

public/main.css begins with a U+FEFF BOM. read_text() keeps it, so the bundler
emitted "<style>:root{...}". A BOM is stripped when a stylesheet is FETCHED
with a charset; inside an inline <style> it is not, and ":root" is an invalid
selector -- so the browser dropped that entire first rule.

That first rule is the dark base palette. Consequences:

  light mode  fine, because the light overrides come later and parse
  dark  mode  every custom property unset -- tokens rendered rgb(0,0,0), the
              ground rgba(0,0,0,0). Black text on transparent.

Anyone opening the deck on a dark-mode machine got a broken page, and nothing in
the light-mode preview could reveal it. Found by testing both themes rather than
the one my browser happened to be in.

Fixed by stripping the BOM when inlining. Verified on the rebuilt bundle:

  light  tok-kw #7c3aed  ground rgb(244,239,228)  text rgb(26,34,53)
  dark   tok-kw #c084fc  ground rgb(15,17,23)     text rgb(225,228,237)

Both themes now define all six syntax colours and both grounds render.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
Slide 12 showed a verified own<dma-buffer> handoff and stopped there, which reads
as a private seam. It is the embedded, verified instance of a general direction:
shared-memory objects as a canonical-ABI option, where attach and detach ARE the
ownership transfer.

The alignment worth saying out loud is that the awkward case is our normal one --
the host answering zero and handing back a FIXED address, MPU rather than MMU, is
exactly meld merged-memory plus synth --native-pointer-abi on an 8 KB part. That is
a corner for most people and the default for us, which is the useful thing we can
contribute to it.

Grounded in FIND-DMA-SHM-CANONICAL-001 (artifacts/gust_dma_model.yaml), which
records the design reference and that its author is aware of the work. Named the
design reference rather than gesturing at "prior art", since half-credit was the
reason an earlier slide got cut.

Deliberately NOT included: a second attribution I could not ground. It appears in
no artifact, doc or measurement in this repo, and the article offered as the source
is by a different author and contains no substantive shared-memory content -- only
a forward reference that shared-everything threads come after Component Model 1.0.
Left out pending confirmation rather than asserted on a public slide.

Slide 12 reports a 6 px overflow at 4:3 that is bottom padding, not content: its
last line clears the nav by 59 px, measured.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
The outlook cited a design reference but not the question behind it. The framing
question is Luke Wagner's "Does the Component Model Require Extra Copying?", and at
8 KB it is not academic -- a copy at the seam is a copy we cannot afford.

So the slide now leads with the question and gives our answer: attach and detach ARE
the transfer, not a hand-off plus a copy. The body says "a transfer, not a copy"
explicitly, which is the thing the ledger's 220 B / 0 SRAM / 6 Kani proofs is
evidence for.

Both references named -- Luke Wagner for the question, Christof Petig's wasm-shm-test
for the design. Recorded in gale as FIND-DMA-SHM-CANONICAL-001 (gale#256), checked
against the sources rather than recalled.

Slide 12 reports 19 px overflow at 4:3 that is bottom padding, not content: its last
line clears the nav by 46 px, measured.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
The outlook was set at the .slide__cite default of 92ch, so it wrapped into a tall
four-line column in the left two-thirds while the right third sat empty -- competing
with the body block above it for the same measure, which is what made the slide feel
crowded rather than full.

Added .slide__cite.is-wide (max-width: 100%) and applied it. Width alone was not
enough -- it went 837 -> 922 px at 4:3 and the height did not move, because the text
still wrapped to four lines -- so the outlook and the body paragraph were both cut.

  body paragraph  119 -> 79 px
  outlook         157 -> 131 px
  slide 12        19 px over -> ZERO, clearing the nav by 65 px

Zero overflow and zero clipped elements across all 38 slides at 1440x900, and only
slide 4's known padding-only 10 px at 1024x768. The outlook spans 1296 px at 16:10.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
…vered deck

Two sections were doing one job, and one of them was half-built: talks/ was
`render = false` and absent from the nav, so publishing the deck would have put it
on the site reachable only by direct URL.

Merged into content/publications/ -- "what we wrote for people". reports/ stays
separate: it is what the TOOLS produced (rivet compliance, witness MC/DC), which is
a different kind of artifact.

Live URLs preserved by alias, verified in the built output:
  /preprints/oracle-gated-agent-loops/ -> /publications/oracle-gated-agent-loops/
  /talks/wasm-research-day-2026/       -> /publications/wasm-research-day-2026/

The deck is published; the speaker notes are NOT -- draft = true, kept in the repo.

Two bugs found on the way:

1. `aliases` landed after [taxonomies], so Zola read it as a taxonomy and the build
   failed outright. Moved above the block.

2. Worse, because it was silent: tools/bundle-talk.py still pointed at the OLD slug,
   which now resolves to the alias REDIRECT STUB. It happily produced a 483 B file --
   fonts inlined, exit 0, "success" -- and would have overwritten the 652 KB deck
   with a redirect page. Fixed the slug and added a guard that refuses to write when
   the source has no slides. Verified the guard fires on the stale path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
@avrabe
avrabe marked this pull request as ready for review August 6, 2026 17:06
@avrabe
avrabe merged commit a025470 into main Aug 6, 2026
1 check passed
@avrabe
avrabe deleted the talk/wasm-research-day-2026 branch August 6, 2026 17:25
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