Skip to content

Commit 1fc031a

Browse files
Phase H.2: autofix-and-retry loop + divide-by-singularity check
examples/self_healing_h2.omc — the healer becomes iterative and gains a third diagnostic class. New diagnostic class: divide-by-singularity. In heal_expr, when a BIN `/` operator's right operand is a literal NUM, the healer evaluates value_danger(v). If the result exceeds 0.5 (fold_escape's danger threshold), the whole expression is rewritten as CALL safe_divide(left, right). The host's safe_divide primitive does the rest — it fold_escapes the divisor at runtime, so safe_divide(8, 0) returns 8 (8 / fold_escape(0) → 8 / 1 → 8), not an error. The healer turns a runtime crash into a finite answer that lands on a Fibonacci attractor, with no special-case error-handling code anywhere. The math is the rule. The loop heal_until_fixpoint(stmts, max_iter): for iter in 1..max_iter: (healed, diags) = heal_program(current) record (iter, |diags|) in trajectory if |diags| == 0: return ("converged", iter - 1) if |diags| == prev: return ("stuck", iter) current = healed return ("exhausted", max_iter) Three terminal states: converged, stuck, exhausted. Three demos, three convergences: Demo 1 (H.1 regression): 12→13, fbi→fib. fib(13) = 233. Demo 2 (new): numerator / 0 → safe_divide(8, 0) → 8. Demo 3 (all three): 7→8, safef→safe, n/0 → safe_divide(n,0). The bytecode VM gains ONN primitive dispatch: safe_divide, fold_escape, value_danger, harmony_value, is_fibonacci. Healed programs run end-to-end on the V.7c executor without falling back to tree-walk. Why iteration matters even when one pass suffices: H.1's checks already run in parallel during one AST walk. H.2's loop is mostly empty-confirmation passes. But the LOOP IS THE RIGHT SHAPE for H.3 (parse-level recovery: rewrite-and-re-parse is naturally iterative) and H.4 (runtime-guarded primitives: adding a guard can expose new diagnostics on adjacent nodes). H.2 lands the substrate so H.3/H.4 plug in without re-architecting. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 7c59537 commit 1fc031a

2 files changed

Lines changed: 1969 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,58 @@ All notable changes to OMNIcode will be documented in this file.
44

55
## [Unreleased]
66

7+
### Added (Phase H.2: autofix-and-retry loop + divide-by-singularity check, 2026-05-13)
8+
9+
🎯 **`examples/self_healing_h2.omc` — the healer becomes iterative and gains a third diagnostic class.**
10+
11+
H.1 was a single-pass scanner. H.2 wraps it in a convergence loop and adds runtime-singularity awareness.
12+
13+
#### New diagnostic class: divide-by-singularity
14+
15+
In `heal_expr`, when a `BIN /` operator's right operand is a literal `NUM`, the healer evaluates `value_danger(v)`. If the result exceeds 0.5 (fold_escape's danger threshold), the whole expression is rewritten as `CALL safe_divide(left, right)`. The host's `safe_divide` primitive does the rest — it fold_escapes the divisor at runtime, so `safe_divide(8, 0)` returns `8` (8 / fold_escape(0) → 8 / 1 → 8), not an error.
16+
17+
The key property: **the healer turns a runtime crash into a finite answer that lands on a Fibonacci attractor**, with no special-case error-handling code anywhere. The math is the rule.
18+
19+
#### The loop: `heal_until_fixpoint`
20+
21+
```
22+
fn heal_until_fixpoint(stmts, max_iter):
23+
for iter in 1..max_iter:
24+
(healed, diags) = heal_program(current)
25+
record (iter, |diags|) in trajectory
26+
if |diags| == 0: return ("converged", iter - 1)
27+
if |diags| == prev: return ("stuck", iter)
28+
current = healed
29+
return ("exhausted", max_iter)
30+
```
31+
32+
Three terminal states:
33+
- **converged** — diagnostics dropped to zero. Healed source stable.
34+
- **stuck** — same count two iterations running. Healer can't make progress.
35+
- **exhausted** — hit the safety bound. Likely a divergent rewrite cycle.
36+
37+
Tonight's demos all converge cleanly. `stuck` and `exhausted` are exercised in H.3/H.4.
38+
39+
#### Three demos, three convergences
40+
41+
**Demo 1** (H.1 regression): `12 → 13`, `fbi → fib`. Iter 1: 2 diagnostics → Iter 2: 0. Output: `fib(13) = 233`. Verdict: converged in 1 iteration.
42+
43+
**Demo 2** (new): `numerator / 0`. The harmonic check fires on `10 → 8`; the divide-by-singularity check rewrites the division. Healed program: `safe_divide(8, 0)` → host fold_escape's 0 to 1 → returns 8. **Runtime crash converted to finite answer on attractor.**
44+
45+
**Demo 3** (all three): `7 → 8` (harmonic), `safef → safe` (typo), `n / 0 → safe_divide(n, 0)` (singularity). One pass through `heal_program` fans the three classes out over the AST and rewrites all three in parallel. Output: `safe(8) → 8`.
46+
47+
#### Bytecode VM gains ONN primitives
48+
49+
`is_builtin` and `call_builtin` in the V.7c-style executor now dispatch `safe_divide`, `fold_escape`, `value_danger`, `harmony_value`, and `is_fibonacci`. The healed programs can be executed end-to-end without falling back to tree-walk — the bytecode VM hosts the φ-math primitives the healer rewrites toward.
50+
51+
#### Why iteration matters even when one pass suffices
52+
53+
H.1's checks already run in parallel during one AST walk. H.2's loop is mostly empty-confirmation passes (iter 2 always shows 0 diagnostics). But the LOOP IS THE RIGHT SHAPE for upcoming additions:
54+
- **H.3** — parse-level recovery. A syntax error rewrite produces a new AST that needs to be re-parsed and re-healed. Naturally iterative.
55+
- **H.4** — runtime-guarded primitives surfaced as OMC keywords. Adding a guard around an expression changes the AST in ways that may expose new diagnostics on adjacent nodes.
56+
57+
H.2 lands the substrate so H.3/H.4 plug in without re-architecting.
58+
759
### Added (Phase H.1: Self-Healing Compiler — harmonic + typo diagnostics, 2026-05-13)
860

961
🎯 **`examples/self_healing_compiler.omc` — OMC's φ-math becomes a diagnostic lattice the compiler reasons against.**

0 commit comments

Comments
 (0)