# Live defects found

Every one compiled clean, ran, and produced a wrong result or a crash with **no
diagnostic at any layer**. All four were present before this session; none was
introduced by it.

## Silent miscompilations

### 1. An unannotated `let` loses its type

```el
let a = str_len("hello")     // no annotation
let b = str_len("hi")
let c = a + b                // → el_str_concat(a, b) on two integers
```

Compiled clean. Printed **nothing** where it should print 7. Fixed: an
unannotated `let` takes its type from what its initialiser returns. The return
types were already required for dispatch and were simply never consulted at the
binding site.

### 2. Reserved keywords that reserved nothing

```el
let seed = 42
let impl = seed + 1
```

`sealed`, `activate`, `seed`, `protocol`, `impl` were keywords in the lexer and
consumed by no parser or codegen path. Using one did not fail to parse — it
compiled clean, with zero `cc` errors, and printed **0 instead of 44**. Fixed by
removing all five.

### 3. `Instant + Int` was never refused

```el
let t: Instant = now()
let u: Instant = t + 3       // → (t + 3), reported clean
```

`Duration + Int` was refused — *"an Int carries no unit"* — while adding a
dimensionless number to a **point** silently moved the instant by an
unspecified amount. Three of *what*? Whatever the representation happens to be.
The rule was simply never written.

## Security-relevant

### 4. Annotations are never verified

```el
let x: Int = "hello"; x + 1     →  4343631981   a string POINTER used as an integer
let s: String = 42; println(s)  →  nothing      address 42 dereferenced
```

The first **leaks a raw memory address into program output**. The second is an
**arbitrary-read primitive** if the integer is ever attacker-influenced.

### 5. `sha256_hex(<integer>)` segfaults

```el
let h: String = sha256_hex(50000)    →  exit 139, SIGSEGV
```

Compiled clean. `el_bin_lookup` checked only a 4096 floor — no alignment, no
small-int, no negative — and reads **eight bytes backward** from the pointer.
And the actual crash was one level further on: `el_input_len` fell through to
`strlen()` on address 50000, because a NULL check does not establish that a slot
is a pointer.

Fixed, and the guard is now a **gate**: `el_tagged()` is exported in
`el_runtime.h`. `geom_of` and `mfld_of` were always correct because their authors
knew to call `looks_like_heap_obj`; `el_bin_lookup` and `el_input_len` were wrong
because theirs did not, and the function was `static`, so every sibling
translation unit re-derived it.
