writeonce/docs/plan/oop-vm
shoney.arickathil 934780c54c feat(compiler): ?T forced handling — WO-E211/E212/E213 + narrowing (iter 5)
The type system now keeps its nullability promise: a `?T` value cannot be
used, stored, or dereferenced as a plain `T` without narrowing. The canonical
evidence probe (return b.v where v: ?Int, fn -> Int) that compiled clean for
months now fails with WO-E211.

- WO-E211 (un-narrowed use): arithmetic and </<=/>/>= operands, and/or
  operands (?Bool), interpolation segments, for-iterables, and returns whose
  declared type is not nullable.
- WO-E212 (boundary): nil or ?T stored into a non-nullable slot — annotated
  let, assignment to a confidently-typed local (cenv, never the placeholder
  env — a placeholder target must stay silent) or a resolvable class field.
- WO-E213 (deref): field/index access through a possibly-nil base.
- Narrowing (locals only — a field place can be re-assigned between check
  and use, so chains bind to a local first): `if x != nil { }` narrows the
  branch; a DIVERGING then-branch (`if x == nil { return }`) narrows after
  the if; `x != nil and x.n > 3` narrows and/or right operands
  (short-circuit); `while x != nil` narrows the body. The narrow is
  un-applied when an else-less then-env leaks out un-diverged (the existing
  env-leak convention must not leak the narrow).
- No false positives by construction: env/cenv types are declared or
  confidently inferred; the placeholder fallbacks are plain scalars, never
  ?T. The whole golden suite passed untouched (540/0).
- Samples updated to the bind-then-narrow idiom (log-watcher config decode +
  supervisor lock/next_fire, gc-cycle ring print) — 22 genuine unnarrowed-nil
  sites; employee needed zero changes. All acceptances green.
- Corpus: compile-fail/{nullable-unnarrowed-use,nullable-nil-into-plain,
  nullable-deref-unchecked} + run/nullable-narrowing (all four forms) — 83/0.
- Catalog: E211/E212/E213 move from "Reserved, not yet emitted" to the main
  table; nullable-types-implementation.md status flipped to ENFORCED
  (historical record kept); plan 8 Task 6 ticked (boxed scalar cells
  superseded by WO_NIL_SCALAR); board updated.

Verified: woc-test 540/0 + test_diag 14/0; oop-e2e 83/0; oop-accept ALL MET;
log-watcher 7/0; employee 8/0; gc-cycle ring prints + reclaims.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 17:47:13 +02:00
..
00-wob-format.md docs: iteration 7b migration — amend the normative docs (Phase 4) 2026-08-19 17:11:35 +02:00
01-error-catalog.md feat(compiler): ?T forced handling — WO-E211/E212/E213 + narrowing (iter 5) 2026-08-19 17:47:13 +02:00
02-corpus.md feat(compiler): iteration 5 Tasks 1-4 — modules, language surface, switch, typedef records + enum variants 2026-08-12 14:40:07 +02:00
04-db-binding.md feat: insert executes (iteration 9, Task 3) -- DB_STUB retires for insert 2026-08-15 11:15:06 +02:00
08-builtin-surface.md docs: iteration 7b migration — amend the normative docs (Phase 4) 2026-08-19 17:11:35 +02:00
README.md feat: milestone 1 complete — .wob emitter, conformance corpus, single binary; GC redesign specced 2026-08-11 19:31:26 +02:00

docs/plan/oop-vm/ — OOP + systems track contracts

The normative contract documents both stacks cite. Landed by their named plan tasks:

doc contract plan
00-wob-format.md .wob bytecode format (compiler↔VM) 1
01-error-catalog.md every WO-E### code 2, grows 3/8
02-corpus.md how to add conformance fixtures 3
03-shard-actor.md shard ownership, mailboxes, send-as-move 4
04-db-binding.md row format, WAL records, query subset 5
05-http-service.md route section, trap→HTTP table, JSON subset 6
06-ui-live.md delta frames, subscribe protocol, wo:live 7
07-systems-stdlib.md per-function nil-vs-trap contracts 9
08-builtin-surface.md builtin source names, container/call/entry rules the emitter enforces 3

Specs and plans: docs/superpowers/{specs,plans}/. Repo map: docs/08-project-structure.md.