Skip to content

Commit 1b96175

Browse files
Error message knowledge base: 259 curated patterns + omc_explain_error
Comprehensive error catalog in omnimcode-core/src/errors.rs covering 259 distinct error niches across 14 categories. LLMs catching OMC errors call omc_explain_error(msg) and get back a structured dict with what the error means, the typical cause, and the one-line fix — no need to memorize the entire surface. The catalog has two layers: (1) ~42 hand-written entries for the high-traffic / nuanced cases: did_you_mean dispatch, index-out-of-bounds, matmul shape mismatch, ragged 2D arrays, broadcast length mismatch, parser "Expected Semicolon" / "Expected identifier", JSON, base64, regex, etc. — each with cause + idiomatic fix. (2) 217 auto-generated entries, one per builtin that asserts arity. Same structure: pattern → category → explanation → fix-hint pointing at omc_help("<name>") for the right signature. Three new introspection builtins: omc_explain_error(msg) — match + structured dict back omc_error_categories() — list buckets in the catalog omc_error_count() — knowledge-base size (259 today) The catalog itself is rendered by docs/render_full_errors() — wireable into the next --gen-docs-style export. Tests: 7 cases covering matched + unmatched lookups against the live runtime, dispatch / arrays / linalg / substrate categories. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent d5cbf17 commit 1b96175

6 files changed

Lines changed: 789 additions & 1 deletion

File tree

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# Error catalog — omc_explain_error pattern-matches runtime errors
2+
# against a curated knowledge base and returns structured remediation.
3+
#
4+
# LLMs catching OMC errors call this to get back actionable fixes
5+
# without having to memorize the 200+ error niches.
6+
7+
fn assert_eq(actual, expected, msg) {
8+
if actual != expected {
9+
test_record_failure(msg + ": expected " + to_string(expected) + " got " + to_string(actual));
10+
}
11+
}
12+
13+
fn assert_true(cond, msg) {
14+
if !cond { test_record_failure(msg); }
15+
}
16+
17+
# ---- omc_error_count ----
18+
19+
fn test_error_count_substantial() {
20+
h n = omc_error_count();
21+
assert_true(n >= 40, "catalog has at least 40 patterns");
22+
}
23+
24+
# ---- Pattern matching against a real runtime error ----
25+
26+
fn test_explain_undefined_function() {
27+
h err = "";
28+
try {
29+
h _ = arr_softmx([1.0]); # typo
30+
} catch e {
31+
err = e;
32+
}
33+
h ex = omc_explain_error(err);
34+
assert_eq(dict_get(ex, "matched"), 1, "pattern matched");
35+
assert_eq(dict_get(ex, "category"), "dispatch", "category is dispatch");
36+
assert_true(str_len(dict_get(ex, "fix")) > 0, "fix is non-empty");
37+
}
38+
39+
fn test_explain_index_out_of_bounds() {
40+
h err = "";
41+
try {
42+
h xs = [1, 2, 3];
43+
h _ = arr_get(xs, 99);
44+
} catch e {
45+
err = e;
46+
}
47+
h ex = omc_explain_error(err);
48+
assert_eq(dict_get(ex, "matched"), 1, "out-of-bounds matched");
49+
assert_eq(dict_get(ex, "category"), "arrays", "category arrays");
50+
}
51+
52+
fn test_explain_matmul_shape_mismatch() {
53+
h err = "";
54+
try {
55+
h A = [[1, 2, 3]];
56+
h B = [[1, 2]]; # wrong shape for matmul
57+
h _ = arr_matmul(A, B);
58+
} catch e {
59+
err = e;
60+
}
61+
h ex = omc_explain_error(err);
62+
assert_eq(dict_get(ex, "matched"), 1, "matmul shape matched");
63+
assert_eq(dict_get(ex, "category"), "linalg", "linalg category");
64+
}
65+
66+
# ---- Pattern matching on unknown error returns matched=0 ----
67+
68+
fn test_explain_unknown_error() {
69+
h ex = omc_explain_error("this error has no catalog entry whatsoever 12345 xyz");
70+
assert_eq(dict_get(ex, "matched"), 0, "no match");
71+
assert_true(str_len(dict_get(ex, "explanation")) > 0, "fallback explanation given");
72+
}
73+
74+
# ---- omc_error_categories ----
75+
76+
fn test_error_categories() {
77+
h cats = omc_error_categories();
78+
assert_true(arr_len(cats) >= 5, "at least 5 error categories");
79+
h has_arrays = 0;
80+
h has_dispatch = 0;
81+
h i = 0;
82+
while i < arr_len(cats) {
83+
h c = arr_get(cats, i);
84+
if c == "arrays" { has_arrays = 1; }
85+
if c == "dispatch" { has_dispatch = 1; }
86+
i = i + 1;
87+
}
88+
assert_eq(has_arrays, 1, "has 'arrays' category");
89+
assert_eq(has_dispatch, 1, "has 'dispatch' category");
90+
}
91+
92+
# ---- Substrate-aware error catalog ----
93+
94+
fn test_explain_substrate_error() {
95+
h err = "";
96+
try {
97+
h _ = arr_substrate_attention([[1, 2]]); # missing K, V
98+
} catch e {
99+
err = e;
100+
}
101+
h ex = omc_explain_error(err);
102+
assert_eq(dict_get(ex, "matched"), 1, "substrate attention error matched");
103+
}

omnimcode-core/src/compiler.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ impl Compiler {
192192
| "mod_pow" | "bit_count" | "bit_length"
193193
| "digit_sum" | "digit_count"
194194
| "arr_unique_count" | "arr_gcd" | "fnv1a_hash"
195-
| "is_instance"
195+
| "is_instance" | "omc_error_count"
196196
// tape_* op constructors return node IDs (int)
197197
| "tape_var" | "tape_const"
198198
| "tape_add" | "tape_sub" | "tape_mul" | "tape_div"
@@ -278,6 +278,7 @@ impl Compiler {
278278
// Introspection / discoverability surface
279279
| "omc_list_builtins" | "omc_categories"
280280
| "omc_did_you_mean" | "omc_unique_builtins"
281+
| "omc_error_categories"
281282
// Forward-mode autograd duals (Track 2 — 2026-05-16)
282283
| "dual" | "dual_add" | "dual_sub"
283284
| "dual_mul" | "dual_div" | "dual_neg"

omnimcode-core/src/docs.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,27 @@ pub const BUILTINS: &[BuiltinDoc] = &[
741741
example: "omc_unique_builtins() // [is_attractor, arr_substrate_attention, ...]",
742742
unique_to_omc: false,
743743
},
744+
BuiltinDoc {
745+
name: "omc_explain_error", category: "introspection",
746+
signature: "(msg: string) -> dict",
747+
description: "Pattern-match an error message against the curated catalog. Returns {matched, pattern, category, explanation, typical_cause, fix}.",
748+
example: "try { arr_softmx([1.0]); } catch e { print(dict_get(omc_explain_error(e), \"fix\")); }",
749+
unique_to_omc: false,
750+
},
751+
BuiltinDoc {
752+
name: "omc_error_categories", category: "introspection",
753+
signature: "() -> string[]",
754+
description: "All distinct error categories in the catalog.",
755+
example: "omc_error_categories() // [dispatch, arrays, linalg, ...]",
756+
unique_to_omc: false,
757+
},
758+
BuiltinDoc {
759+
name: "omc_error_count", category: "introspection",
760+
signature: "() -> int",
761+
description: "Number of curated error patterns. The knowledge base size.",
762+
example: "omc_error_count() // 42+",
763+
unique_to_omc: false,
764+
},
744765
];
745766

746767
/// Look up a builtin by name. Returns None when there's no docs entry

0 commit comments

Comments
 (0)