# Cycle History (append-only) ## Cycle 0 — Research - Read WASM runner implementation end-to-end (5 source files, 3 guest modules, 11 tests) - Wrote feature_map.md, constraints.md, research_synthesis.md (15 ranked test scenarios) - Found potential bug P0-1: missing bounds check in actor.rs:44-46 (copy_from_slice OOB) - Built guest WASM modules, verified all 11 baseline tests pass ## Cycle 1 — P0/P1/P2 Tests + 2 Bug Fixes - Wrote 12 new tests (P0-1 through P2-1), total now 23 - Bug #1 fixed: actor.rs bounds check — alloc OOB ptr caused permanent actor poisoning - Bug #2 found+fixed: worker.rs StopSignal didn't push to deaths — watchers never notified for stop_actor() - All 23 WASM actor tests + 157 core tests pass ## Cycle 2 — P2-2 + P3 Property Tests - Added multi-worker runtime test (P2-2) — Send safety of wasmtime Store verified - Added 2 property-based tests (proptest): echo round-trip + double 2x invariant - All 26 WASM actor tests pass, all scenarios from research_synthesis.md complete ## Cycle 3 — Deep Dive: Stale Outbox + Edge Cases - Bug #3 found+fixed: outbox not cleared on handle trap — stale sends leaked into next call - Added 4 new tests: stale outbox leak, invalid WASM bytes, zero-length payload send, multiple sequential traps - All 30 tests pass ## Cycle 4 — Start Trap, Self-Send, Amplification, Overlap - Added 4 more tests: trapping start function, self-send feedback loop, 10x amplification, overlapping send regions - No new bugs found (all 4 pass) - All 34 tests pass ## Cycle 5 — Type Mismatch, State Persistence, Dynamic Spawn - Added 3 tests: type mismatch handling, guest mutable state persistence, dynamic WASM spawn from handler - No new bugs found - All 37 tests pass ## Cycle 6 — Bounded Mailbox + Alloc Fuzzing - Added bounded mailbox backpressure test (DropNewest policy) - Added property test: any alloc return value (-100..70000) never kills actor - All 39 tests pass ## Cycle 7 — Alloc Trap, memory.grow, Send Overflow, Exact-Fit - Added 4 tests: alloc trapping (store recovery), memory.grow during handle, send with dest_ptr=i32::MAX overflow, exact-fit allocation at boundary - No new bugs found — all edge cases handled correctly - All 43 tests pass ## Cycle 8 — Off-By-One, Lifecycle, Chains, Grow Exhaust - Added 5 tests: alloc returns exactly memory size, spawn-stop without messages, 3-hop relay, 10-hop chain relay, memory.grow until failure - No new bugs found - All 48 tests pass ## Cycle 9 — Send Overflow/Boundary, Cross-Thread, Fuzz Send Args - Added 4 tests: payload range overflow, payload at exact memory end, cross-thread WASM relay, property test fuzzing all send args - No new bugs found - All 52 tests pass ## Cycle 10 — Multi-Dest Sends, Outbox Copy, Large Payload, Alloc-with-Grow - Added 4 tests: two destinations in one handle, memory overwrite after send (outbox copy safety), large payload, alloc that grows memory returns new region pointer - No new bugs found - All 56 tests pass ## Cycle 11 — Message Budget, Data Segments, Outbox Isolation, Combined Fuzz - Added 4 tests: actor_message_budget fairness, data segment initialized memory, two-actor outbox isolation, combined alloc+trap+send property fuzz - No new bugs found — prop_random_module_behavior_never_crashes is strongest general safety property - All 60 tests pass ## Cycle 12 — Stack Overflow, Bulk Memory, Self-Amplification, Double Stop - Added 4 tests: infinite recursion trap, bulk memory.fill, self-amplification bounded by budget, double stop idempotency - Fixed 2 flaky MT tests (poll with retry loop instead of fixed sleep) - All 64 tests pass ## Cycle 13 — SIMD Rejection, Garbage Address, call_indirect, Custom Sections - Added 5 tests: SIMD module rejected by sandboxed engine, garbage address bytes silently dropped, call_indirect dispatch, alloc returning 0 for zero-length message, custom section tolerance - Subtle Ok(0) guard behavior verified: alloc returns 0 + len=0 falls through to handle(0,0) - All 69 tests pass ## Cycle 14 — Multi-Engine, Error Formatting, Rapid Lifecycle, Stop-Send Race - Added 6 tests: actors from different engines coexist, error Display formatting, rapid spawn-process-stop (20 iterations), stop-send race, SharedEngine Debug, ByteMessage traits - No new bugs found - All 75 tests pass ## Cycle 15 — Outbox Flood, Mixed Cleanup, i32::MAX Alloc, Size Fuzz - Added 4 tests: 1000-message outbox flood, interleaved WASM+native actor cleanup, alloc returning i32::MAX, property test for varied payload sizes - No new bugs found - All 79 tests pass (6 property tests) ## Cycle 16 — Spawn+Send Same Tick, 21-Actor Mixed Runtime, Alternating Alloc - Added 3 tests: message delivery on spawn tick, 20 native + 1 WASM actor mixed runtime, alloc alternating -1/256 - No new bugs found - All 82 tests pass ## Cycle 17 — Truncated WASM, No-Import Module, 4-Thread Stress, i32::MIN, Dual Watcher - Added 5 tests: truncated binary, module without send import, 10 actors on 4 threads, i32::MIN alloc, two watchers on same target - No new bugs found - All 87 tests pass ## Cycle 18 — Div-by-Zero, Extra Exports, Zero-Addr, Operation Sequence Fuzz - Added 4 tests: division by zero trap, extra exports tolerated, zero-address send, operation sequence property fuzz - No new bugs found - All 91 tests pass ## Cycle 19 — Integer Overflow Wrapping, Multi-Msg Per Tick, Hot-Swap - Added 3 tests: i32 overflow wrapping, 5 messages in one tick, stop echo + spawn double hot-swap - No new bugs found - All 94 tests pass ## Cycle 20 — memory.copy, 50-Actor Stress, Payload Integrity, Lifecycle Fuzz - Added 4 tests: memory.copy bulk ops, 50 actors from same engine, pattern integrity check, lifecycle fuzz with random stopping - No new bugs found - All 98 tests pass (8 property tests) ## Cycle 21 — OOB call_indirect, All-Guest Integration (100 Tests) - Added 2 tests: OOB table index trap, comprehensive all-guest-module integration - No new bugs found - **100 tests pass milestone** — 3 bugs found and fixed total, 8 property tests, 2 flaky MT tests fixed ## Cycle 22 — OOB memory.fill, Inline Spawn+Send, Sequential Build - Added 3 tests: OOB memory.fill trap, native spawns WASM + sends in same handler, 10 sequential build-use-stop cycles - All 103 tests pass ## Cycle 23 — Conditional Send, Multi-Page, 500-Message Load - Added 3 tests: conditional send based on payload content, 4-page initial memory, 500-message sustained load with integrity check - All 106 tests pass ## Cycle 24 — Mass Spawn/Stop, Echo-to-Stopping, Trait Checks - Added 4 tests: mass spawn/stop of 100 actors, echo to stopping actor, SharedEngine Send+Sync check, WasmActor Send check - All 110 tests pass ## Cycle 25 — XOR Transform, Stop-Respawn, Sequential Shutdown - Added 3 tests: in-place XOR byte transform, stop-respawn 5 rounds, sequential WASM actor shutdown - All 113 tests pass ## Cycle 26 — Ptr/Len Verification, Double with Empty Payload - Added 3 tests: guest receives correct len parameter, correct ptr parameter, double with 0-byte payload - All 116 tests pass ## Cycle 27 — Mixed Outbox, Drop-Oldest, Full Inbox - Added 3 tests: mixed outbox partial delivery, DropOldest mailbox policy, echo to full inbox - All 119 tests pass ## Cycle 28 — Budget-Bounded Echoes, Wrong Signatures, Overlapping Send - Added 4 tests: budget limits per-tick processing, alloc wrong signature rejected, handle wrong return rejected, overlapping dest+payload - All 123 tests pass ## Cycle 29 — Unexported Memory, Multi-Value, Send Boundary - Added 4 tests: memory not exported, multi-value rejected, send dest at exact boundary, send dest 1 past boundary - All 127 tests pass ## Cycle 30 — Reftype Rejection, Trap Isolation, Negative Alloc, Global Counter - Added 4 tests: externref rejected, trap doesn't affect sibling, negative alloc drops, global counter persists - All 131 tests pass ## Cycle 31 — Zero-Length Send, Separate Engines, 50-Round Stress, Start Function - Added 4 tests: zero-length payload delivers, two engines coexist, 50 spawn-send-stop rounds, start function init - All 135 tests pass ## Cycle 32 — Random Payload Fuzz, Multi-Page Data, Conditional Fan-Out, Advancing Alloc - Added 4 tests (1 property): random payloads never panic, data segments across 3 pages, command-byte dispatch, proper bump allocator - All 139 tests pass ## Cycle 33 — Outbox Snapshot, Grow-Per-Alloc, Trap-After-Send, Offset-Zero Send - Added 4 tests: outbox snapshots at send time, memory.grow per alloc, trap clears valid outbox entries, offset 0 valid - All 143 tests pass ## Cycle 34 — From, 2-Thread 3-Actor MT, If/Else Branching - Added 3 tests: From conversion, 3 WASM actors on 2 threads, if/else dispatch - All 146 tests pass ## Cycle 35 — Loop Sum, dest_ptr=0, Stop-With-Pending, Truncated WASM Fuzz - Added 4 tests (1 property): loop-based byte sum, dest_ptr=0 valid, stop with pending msgs, truncated WASM never panics - All 150 tests pass ## Cycle 36 — FIFO Ordering, Payload Overflow, 100-Send Burst, br_table - Added 4 tests: message FIFO order, payload ptr overflow traps, 100 sends in one handle, br_table dispatch - Fixed prop_truncated_wasm test (renamed, relaxed assertion) - All 154 tests pass ## Cycle 37 — Mutual Watch, Select Instr, WASM-WASM-Native Relay, Dest Addr Fuzz - Added 4 tests (1 property): watcher notified on stop, select instruction, 3-layer relay, arbitrary dest address - All 158 tests pass ## Cycle 38 — Native Spawns WASM, Many Locals, 1000 Ticks, Send-To-Dead - Added 4 tests: native handler spawns WASM, 4-local arithmetic, 1000+ tick survival, send to dead actor - All 162 tests pass ## Cycle 39 — Static Alloc Overwrite, Nested Blocks, memory.size, Spawn-Stop Fuzz - Added 4 tests (1 property): same ptr overwrite, nested block/br, memory.size instruction, lifecycle fuzz - All 166 tests pass ## Cycle 40 — Pre-Filled Memory, Engine Clone, i64 Ops, 200-Actor Stress - Added 4 tests: host overwrites pre-filled memory, cloned engine works, i64 arithmetic, 200 actors - All 170 tests pass ## Cycle 41 — Address-Only Msg, Last Byte, Overlapping Alloc, Wrong Name, Fan-In - Added 5 tests: 32-byte message, write offset 65535, static alloc overwrite, "heap" export, 5-inbox fan-in - All 175 tests pass ## Cycle 42 — Internal Calls, Raw WAT, Build-Discard, Float Ops, Empty Bytes - Added 5 tests: helper functions composed, WAT-compiled silent, 100 build+drop, f64 arithmetic, empty bytes error - All 180 tests pass ## Cycle 43 — Funcref Table, Concurrent Build, memory.copy, Error Traits - Added 4 tests: call_indirect through funcref table, 4-thread concurrent build, bulk memory.copy, Send+Sync check - All 184 tests pass ## Cycle 44 — All 256 Bytes, memory.fill, Watched Actor, Double 0xFF - Added 4 tests: all byte values round-trip, memory.fill response, watched actor lifecycle, double with 0xFF - All 188 tests pass ## Cycle 45 — 4KB Round-Trip, Payload Length, Odd Alignment, Idle Ticks - Added 5 tests: 4KB payload, guest reports length, alloc returns 1, engine clone debug, 500 idle ticks - All 193 tests pass ## Cycle 46 — 200 TEST MILESTONE - Added 7 tests (1 property): mixed WASM+native, byte sum, single byte echo, no-function module, size-varying response, determinism property, all-guest lifecycle - **200 tests pass milestone** ## Cycle 47 — Page Boundary Exact/OOB, Multiple Runtimes, Full Message Mirror - Added 4 tests: exact page boundary alloc, 1 past boundary drops, two runtimes, full msg mirror - All 204 tests pass ## Cycle 48 — Self-Send, Bit Rotation, Bit Counting, Selective Stop - Added 4 tests: self-send bounce, i32.rotl, clz/ctz/popcnt, stop every other actor - All 208 tests pass ## Cycle 49 — i32 Store/Load, eqz, Silent 1000-Msg, Pre-Tick Delivery - Added 4 tests: LE i32 store/load, eqz instruction, silent processes 1000 msgs, pre-tick delivery - All 212 tests pass ## Cycle 50 — Modulo, 8KB Echo, Duplicate Sends, Full Lifecycle Fuzz - Added 4 tests (1 property): i32.rem_u, 8KB round-trip, 5 duplicate sends, combined lifecycle fuzz - All 216 tests pass ## Cycles 51-57 — Continued Coverage Expansion - Cycle 51 (220): XOR transform, address reconstruction, double+watch, constructors - Cycle 52 (224): shift ops, AND/OR, echo+double coexist, i16 load - Cycle 53 (228): repeated build independence, stale memory read, guest module fuzz, 3-deep calls - Cycle 54 (232): grow+send from new page, 20×20 stress (400 msgs), minimal module, data segment template - Cycle 55 (236): raw inbox send, multi data segments, 100 ticks, nop instructions - Cycle 56 (240): interleaved spawn, store16, min/max via select, runtime drop with live actors - Cycle 57 (244): immutable global, 5 round-trips, builder ownership, empty tick ordering ## Cycle 58 — Reverse Payload, Extra Exports, Comprehensive Fuzz - Added 6 tests: guest reverses payload, extra exports tolerated, comprehensive guest fuzz, respawned actor address, echo+double separate inboxes, builder slice ref - All 250 tests pass ## Cycle 59 — local.tee, 16KB Payload, Dual Runtime, i64 Wrap - Added 5 tests: local.tee instruction, 16KB payload round-trip, two independent runtimes, i64-to-i32 wrap, random WAT variations property test - All 255 tests pass ## Cycle 60 — Three Destinations, Tick-Per-Msg, 10-Page Memory - Added 5 tests: three echo destinations, one-message-per-tick for 10 ticks, 10-page initial memory, fill+copy together, stop with pending messages - All 260 tests pass ## Cycle 61 — Unreachable, Bump Alloc, Control Flow, N-Spawn Fuzz - Added 5 tests: unreachable trap recovery, bump allocator advancing, block/loop/br_if, stop one of two, property test spawning 1..20 actors - All 265 tests pass ## Cycle 62 — Self-Send Budget, Empty Module, Static Alloc, 32KB Echo - Added 5 tests: self-send loop bounded by budget, empty module rejected, static alloc echoes, two engines two runtimes, 32KB payload - All 270 tests pass ## Cycle 63 — Zero-Len Send, Overlapping Regions, Alloc Exhaustion - Added 4 tests: zero-length payload from guest, overlapping dest/payload, alloc exhaustion drops gracefully, stop all actors - All 274 tests pass ## Cycle 64 — Outbox Clear on OOB Send, Sign Extend, 60KB Echo - Added 5 tests: send then OOB send clears outbox, sign extension, double processes then stops, near-page echo (60KB), property echo preserves arbitrary content - All 279 tests pass ## Cycle 65 — Alloc Trap Recovery, Unused Table, Alternating Sizes - Added 5 tests: alloc trap then normal message, unused table, alternating large/small, silent absorbs 200, two actors from cloned bytes - All 284 tests pass ## Cycle 66 — 100-Tick Longevity, Nested If/Else, Engine Drop - Added 5 tests: logical right shift, 100 messages across 100 ticks, three-deep if/else, increasing payload sends, engine dropped after build - All 289 tests pass ## Cycle 67 — Memory Grow, Native Verifier, Zero-Page, Stop Fuzz - Added 6 tests: grow memory and use new page, native verifier, sequential lifecycle, zero-page memory, double receives two messages, stop-with-pending property test - All 295 tests pass ## Cycle 68 — 300 TEST MILESTONE - Added 5 tests: write offset zero, 10 echo actors respond, alternating silent/sending, budget=1 one-per-tick, echo address-only - **300 tests pass milestone** — 3 bugs found and fixed total, 20 property tests ## Cycles 69-79 — Continued Expansion to 350 - Cycle 69 (305): multiple globals, large data segment, i64 store, runtime drop - Cycle 70 (309): dynamic send count, 3-actor pipeline, XOR transform - Cycle 71 (314): f32 ops, nested blocks, mixed guest response fuzz - Cycle 72 (319): byte checksum, 4-thread MT stress, comparison ops - Cycle 73 (324): conditional trap, 3 runtimes share engine, 1000 actors - Cycle 74 (328): message counter global, DropOldest mailbox, odd-length filter - Cycle 75 (333): 8-param function, native relay, any-size round-trip fuzz - Cycle 76 (337): dual-address send, 500 messages, early return - Cycle 77 (341): reverse+echo, shared budget, f64, replacement cycle - Cycle 78 (346): fibonacci recursion, 5-actor inbox, block result - Cycle 79 (350): zeros/ones, double fuzz, 30 mixed actors ## Cycles 80-88 — Push to 400 - Cycle 80 (355): length prefix, ping-pong, build+drop, broadcast - Cycle 81 (360): bitwise NOT, MT stop, i64 extend, tick interleave fuzz - Cycle 82 (365): max byte, own address, rapid engines, 256 single-bytes - Cycle 83 (370): 1000-msg stress, typed locals, heterogeneous WAT - Cycle 84 (374): i32 invert, native spawns WASM handler, factorial, determinism - Cycle 85 (379): non-aligned payload, 5x grow, ByteMessage clone, budget overflow - Cycle 86 (383): conditional double, 200-tick longevity, AND mask - Cycle 87 (389): OR mask, 500 actors, bitwise fuzz, last byte modification - Cycle 88 (400): **400 TEST MILESTONE** — byte swap, cross-thread build, FIFO ## Cycles 89-92 — Final Push to 419 - Cycle 89 (405): running sum, parallel build 10 actors, alloc degradation - Cycle 90 (410): mixed payloads, i64 global, stopped-never-responds fuzz - Cycle 91 (414): double-byte saturate, 20 MT actors, 100KB OOB graceful drop - Cycle 92 (419): byte count threshold, reuse slot, missing handle export, 1000 empty ticks ## Campaign Summary (final) - **~98 commits** on bin-runner branch (3 bug fixes + ~95 test/doc commits) - **419 tests** (387 scenario + 28 property + 4 compile-time checks) - **92 cycles** completed (research + 91 test cycles) - **3 bugs found and fixed** in core WASM actor code and runtime - **2 flaky MT tests fixed** with retry polling - **~13,400 lines** of test code - Implementation proved extremely robust after initial 3 bug fixes - No new bugs found after Cycle 3 despite 89 additional test cycles