Found in a modularity review of main @ 8e8970a. Tracking issue. The registration seam is clean for 3 of 5 extensions; the other two bypass it, and the "compose the global env" sequence is open-coded in several places that have already diverged.
1. Two extensions bypass the single registration seam
builtins.c:7386-7396 registers http/db/model behind exactly three #ifs — a genuine single point. But gfx and store are registered by hand elsewhere:
eigs_embed.c:25 register_store_builtins(global);
ext_http.c:1280 register_store_builtins(global);
lint.c:152 register_store_builtins(e);
lint.c:2385 register_store_builtins(e.bind);
main.c register_store_builtins(...) / register_gfx_builtins(...)
register_gfx_builtins is declared at main.c:11 and called only from main.c. So a make gfx build used through the embedding API has no gfx builtins at all — eigs_embed.c never calls the gfx registrar. EIGS_GFX_BUILTINS already exists in ext_names.h:27 precisely to make that cheap, so the mechanism is present and unused.
A fifth registrar today requires N hand-edits across these sites: the exact drift class ext_names.h was built to eliminate, unsolved one level up.
Fix: one register_all_builtins(Env*) that every entry point calls, with the #ifs inside it.
2. Four builtin-name registries, only two gated — and the ungated one is 24% complete
235 builtins are registered in builtins.c. Four independent registries must track them:
| Registry |
Gated? |
State |
SANDBOX_ALLOW[] (builtins.c:4271-4320) |
yes — tests/test_sandbox_allow.eigs |
148 entries, 0 phantom |
docs/BUILTINS.md / SPEC.md / STDLIB.md |
yes — tools/stdlib_index_check.sh |
clean |
builtin_docs[][2] (src/eigenlsp.c:26) |
no |
68 entries — 167 of 235 builtins absent, plus a phantom exec |
lsp_stdlib_index.h |
generated |
correct by construction |
Verified by counting: awk '/builtin_docs\[\]\[2\]/,/^};/' src/eigenlsp.c | grep -c '{"' → 68.
The two gated registries are at zero drift. The ungated one fell to 24% coverage precisely because nothing checks it — so LSP hover and completion silently omit three quarters of the language. This is the cleanest natural experiment in the repo for the value of a gate, and the fix is to point tools/stdlib_index_check.sh's existing extraction at eigenlsp.c too (or generate builtin_docs the way lsp_stdlib_index.h is already generated).
Related: map/filter/reduce/reverse appear in both the hand-written table and the generated stdlib_docs, with no reconciliation between them.
Found in a modularity review of
main@8e8970a. Tracking issue. The registration seam is clean for 3 of 5 extensions; the other two bypass it, and the "compose the global env" sequence is open-coded in several places that have already diverged.1. Two extensions bypass the single registration seam
builtins.c:7386-7396registers http/db/model behind exactly three#ifs — a genuine single point. But gfx and store are registered by hand elsewhere:register_gfx_builtinsis declared atmain.c:11and called only frommain.c. So amake gfxbuild used through the embedding API has no gfx builtins at all —eigs_embed.cnever calls the gfx registrar.EIGS_GFX_BUILTINSalready exists inext_names.h:27precisely to make that cheap, so the mechanism is present and unused.A fifth registrar today requires N hand-edits across these sites: the exact drift class
ext_names.hwas built to eliminate, unsolved one level up.Fix: one
register_all_builtins(Env*)that every entry point calls, with the#ifs inside it.2. Four builtin-name registries, only two gated — and the ungated one is 24% complete
235 builtins are registered in
builtins.c. Four independent registries must track them:SANDBOX_ALLOW[](builtins.c:4271-4320)tests/test_sandbox_allow.eigsdocs/BUILTINS.md/SPEC.md/STDLIB.mdtools/stdlib_index_check.shbuiltin_docs[][2](src/eigenlsp.c:26)execlsp_stdlib_index.hVerified by counting:
awk '/builtin_docs\[\]\[2\]/,/^};/' src/eigenlsp.c | grep -c '{"'→ 68.The two gated registries are at zero drift. The ungated one fell to 24% coverage precisely because nothing checks it — so LSP hover and completion silently omit three quarters of the language. This is the cleanest natural experiment in the repo for the value of a gate, and the fix is to point
tools/stdlib_index_check.sh's existing extraction ateigenlsp.ctoo (or generatebuiltin_docsthe waylsp_stdlib_index.his already generated).Related:
map/filter/reduce/reverseappear in both the hand-written table and the generatedstdlib_docs, with no reconciliation between them.