- emit.ml: a `try … catch (e) nil` is `?T` (ty_of_expr) and the nil arm takes that destination, so a `?Int` nil is WO_NIL_SCALAR and an Int body's legitimate 0 no longer reads as nil (it used to fall back to the zero word via the body type / enclosing return type)
- owner.ml: `transfer` on a projection (`d.tags`, `x[i]`) of an owned value reports WO-E305 instead of returning false silently — the silent path compiled `Out { tags: d.tags }` to an alias that both records dropped (the "json.decode as T corruption": not json's, a double free language 44's poison now aborts on); heap scalars exempt (store sites copy)
- error catalog: WO-E305 row; owner.ml module doc updated
- corpus: run/try-nil-int-zero, compile-fail/no-partial-move, run/decode-record-crosses-return (Text copied, record moved whole — the archived `.. ""` workaround is unnecessary)
- verified: oop-e2e 126/0, tests/regress/lang-41 compile, --emit sweep over the non-porch examples, web-app gate 56/0 (porch in project mode) — no legitimate program trips WO-E305
- story 41: both side defects marked fixed; board prose updated
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 2d54710e693fafee4b8d6561cc9cba7b95415d89)
- pmul_ct: double-and-add-always over the Renes–Costello–Batina complete
projective addition formula (Alg. 4, a=-3) — one exception-free formula for
add and double, identity (0:1:0), so there is NO point-at-infinity branch.
Closes the documented residual: the Jacobian jadd/jdouble ladder's fp_zero
checks leaked k's leading-zero count (a bit-length hint) during ECDSA sign
- wo_ecdsa_p256_sha256_sign uses it; affine x = X * Z^-1 (projective), the
inversion via the constant-time modexp. Dead Jacobian jmul_ct/jpt_cmov removed
- RFC 6979 A.2.5 vectors still byte-exact (test_crypto 130/0); server loopback
(signs with this ladder) still green (test_tls 123/0); ASan/UBSan clean
- docs: rv2 9 review_pending — close_notify + complete-formula ladder moved
from deferred to landed; lang-41 decision 4 fixture marked landed
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit fba30352b965e0f3b749168421a920a832df541b)
Root cause (decision 1): cross-shard send/call/monitor pointer-shared the
message into the receiver's shard (e->payload = msg_val), so a worker read and
eventually dropped an object living in the sender's arena — a double free, then
a class-0 forge, then a modulo self-route livelock, all downstream of that one
broken invariant ("VM heaps are never read cross-shard", which wo_db_rpc keeps).
- actor_marshal: the sender encodes the message into an arena-independent neutral
form (wo_db_val_encode, the same marshal wo_db_rpc uses) and drops its own
original — no pointer crosses an arena boundary, so the double-free class is
gone by construction. actor_unmarshal rebuilds it in the receiver's arena
(wo_val_decode_vm) and frees the neutral. Applied to the 4 cross-shard
producers (send x2, call, monitor) + the 3 consumers (kinds 0/5/7). Same-shard
paths untouched (the WO_SHARDS=1 fast path never failed). Call replies are
scalars by contract, so kind 6 needs no marshal.
- eng_settle_inboxes: undrained kind-0/5/7 payloads at teardown are the neutral
form now — free with wo_db_val_free, not wo_drop_obj (caught by ASan mid-fix).
- decision 2: wo_route_free traps a shard_id >= nshards header (a corrupt/freed
block) instead of self-routing it into the settle livelock.
- proof: tests/regress/lang-41/cross-shard-marshal.wo (a multi<Text> sent +
called cross-shard, both sides drop) — clean 12x/5x under WO_SHARDS=4 + ASan;
shard-settle repro still clean 8x; full runtime suite 0 fail (same-shard
byte-unchanged). `just db-actor` extended with the new fixture.
- unblocks porch 9. Follow-ups: poison-on-free (decision 3), corpus fixture (4).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit 63065ff75799f7f43b2bce6de61e77856799566f)
- jarvis (00-story): 6th track, 2nd software built with writeonce — an AI
assistant; direct-HTTPS design; blockers named (net.connect + TLS)
- runtime-v2 7 observability + 8 symmetric cipher: moved from the language
track (were 30/43); 9 in-process TLS: created from the gap jarvis surfaces,
RETIRES the "TLS is the proxy's job" doctrine (both directions)
- language 41 (arena hang): fix design to ready — marshal cross-shard
messages (root), align the shard_id % nshards route/compare + assert bound;
poison-on-free + minimal fixture as follow-ups
- fiber scope-gap analysis (plan/exploration/fiber/01): porch vs fiber, what
porch lacks, would developers prefer porch
- board + dependency-graph synced (porch 2-8 ready; rv2 table; §5/§5a graphs)
(cherry picked from commit 203470ceb2a151fe3584931cd4237af3f96a9f29)
- root cause: a worker's runtime is initialised lazily on first fiber
adoption, and rt.shard_id is stamped only there — but INBOX_READY[i]
is set at thread creation. A shard that never adopts is still settled
at shutdown, carrying rt.shard_id 0 from the memset
- it then impersonated shard 0: wo_drop_obj saw 0 == 0 for anything the
primary allocated, took the "we are home" branch instead of routing,
and called class_free against rt->classes, which lazy init never
filled. &rt->classes[class_id] off a NULL base is the faulting read
- fix: stamp the runtime's real identity at thread creation. An
uninitialised shard owns nothing, so its true id makes every payload
correctly foreign and routes it to an owner that can free it
- ASan could not name this: the arena is one hand-managed malloc block,
so intra-arena reuse is invisible and it surfaces as a bare SEGV
- pinned by tests/regress/lang-41, driven from db-actor-accept. Needs
multiple shards (the corpus runner pins WO_SHARDS=1) and the ASan
build. SEGVs twice per run unfixed, clean fixed
- the HANG is a separate defect and is NOT fixed: with this in place the
harness stops losing whole sections, but idempotent-stop-2 still
fires ~1 run in 6. The story records where to look
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
(cherry picked from commit 9dca0b4b4727b976d326b29cb4c6522b62d48a73)