This repository has been archived on 2026-08-20. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
el-retired/docs/v1/experiments/evidence/cycles/15-no-namespacing-at-all/CLAIMS.md
T
will d3495476f4
El SDK Release / build-and-release (push) Failing after 13m0s
kill: purge old-paradigm dist/platform binaries from tree
The generated C, amalgams, vendored runtime pins, and compiled binaries
from the Claude Code era are removed from the worktree. The El sources
survive; this tree is now source-only for the first-principles rebuild.

Per Principal direction 2026-08-19.
2026-08-19 19:46:15 -05:00

8.6 KiB
Raw Blame History

CLAIMS — cycle 15, no namespacing at all

Source doc: docs/v1/experiments/cycles/15-no-namespacing-at-all.md

This is the measurement that bears hardest on the hypothesis: if every El symbol binds to a name already resolved by the C linker, the partition question is not being asked yet. It was captured with correspondingly more care than the rest of the set — the linking claim is demonstrated as a six-step chain (00100015), not asserted.

Pinned commits

role sha subject
parent / before-state bb040ad2c record the numeric literals answer: a bare number has no axis
experiment (system under test) 79f6cb79850b5affd7735fcc418ede2242b46e5b ANSWER: if the partition is a neighbourhood, does linking survive?
land (merge) f23cb2b948396eae6a44daac5d56f5e0e6338758 answer the module question: the partition is a path, and there is no namespacing

79f6cb7 touches codegen.el, definitions_query.sh and definitions.sh only. compiler.el — which holds resolve_imports — is unchanged between bb040ad and 79f6cb7, so the import/linking measurements below hold at both.

Verdicts

# claim artifact commit verdict
A1 import is textual inlining (resolve_imports), guarded against double inclusion by a __elc_imp__:<path> state key 0016-resolve-imports-is-textual-inlining.out 79f6cb7 REPRODUCED (exact)
A2 when a .elh header exists the header is inlined instead and the .el is marked seen 0016, 0010, 0011, 0012 79f6cb7 REPRODUCED
A3 so symbols resolve at C link time — linking IS real, delegated to C 0012, 0013-link-D-unresolved-at-c-link-time.out, 0014, 0015 79f6cb7 REPRODUCED (demonstrated end to end)
A4 two modules defining helper emit two C functions into one translation unit 0003, 0004-pre-two-c-functions-one-TU.out bb040ad REPRODUCED (exact)
A5 cc does catch the collision, but reports four errors with the user's own function FOURTH: __el_body_helper, __env_helper, __thunk_helper, helper 0005-pre-cc-collision-error-order.out bb040ad REPRODUCED (exact, in order)
A6 repaired at El level with the message duplicate definition: 'helper' is defined 2 times — El has no namespacing, so imported modules share one global scope 0006-post-el-level-duplicate-message.out 79f6cb7 REPRODUCED (verbatim)
A7 4/4 definitions_query.sh 0007-post-definitions-query-harness.out 79f6cb7 REPRODUCED
A8 104/104 native 0009-post-native-suite.out 79f6cb7 REPRODUCED (exact)
A9 the compiler itself reports clean 0017-compiler-self-check-clean.out 79f6cb7 REPRODUCED
A10 fixpoint ok 0008-post-fixpoint.out 79f6cb7 REPRODUCED
A11 LIMIT: textual inlining destroys file provenance, so the message can name the symbol but not the files 0006 79f6cb7 REPRODUCED
A12 "the first three are generated symbols introduced by the unconditional-wrapper pass earlier today — before it, there was one clear message" NOT-CAPTURED
A13 "El's partition is a FILESYSTEM PATH, not a neighbourhood" / "whether linking survives a neighbourhood partition cannot be asked yet" NOT-CAPTURED (interpretive)
A14 both compilers build 0001, 0002 bb040ad, 79f6cb7 REPRODUCED

A3 — the linking chain, in full

This is the load-bearing measurement. Six captures, one per step. Fixtures fixtures/m.el (defines mhelper) and fixtures/link_main.el (imports it).

A — no header present. resolve_imports inlines the module body; the definition and the call land in one translation unit (0010):

el_val_t mhelper(void);
static el_val_t __el_body_mhelper(void) { return EL_STR("from module m"); }

el_val_t mhelper(void) {  }              <- the DEFINITION is here
int main() { println(mhelper()); }

B — emit a header. elc --emit-header m.el writes (0011):

// auto-generated by elc --emit-header — do not edit
extern fn mhelper() -> String

C — recompile with the header present. The .el is marked seen and the header text is inlined in its place. The whole module body is gone (0012):

#include "el_runtime.h"

el_val_t mhelper(void);                   <- a DECLARATION, and nothing else

int main(int _argc, char** _argv) {
  el_runtime_init_args(_argc, _argv);
  println(mhelper());
  return 0;
}

D — link that translation unit alone. El has produced a program with an unresolved symbol, and says nothing about it. The C linker is what refuses (0013, exit 1):

Undefined symbols for architecture arm64:
  "_mhelper", referenced from:

E — link the module's own translation unit in as well (0014, exit 0):

LINK-OK

F — run it (0015, exit 0):

from module m

The symbol is genuinely unbound at the El layer and genuinely bound by ld. "Linking IS real, delegated to C" is not a characterisation here; it is the observed behaviour of the toolchain at the pinned commit. The El compiler never resolves mhelper — it emits a C declaration and lets the system linker succeed or fail.

A5 — the collision, and the ordering, exactly as recorded

Fixtures fixtures/a.el, fixtures/b.el, fixtures/main.el — two modules each defining helper, one program importing both.

Emitted into one translation unit (0004) — the generated helper trio appears twice, then the user's function twice:

 5: el_val_t helper(void);
 6: el_val_t helper(void);
 8: static el_val_t __el_body_helper(void) {
12: struct __env_helper {  char __e0; };
13: static el_val_t __thunk_helper(void* __v) {
17: el_val_t helper(void) {
25: static el_val_t __el_body_helper(void) {      <- second copy begins
29: struct __env_helper {  char __e0; };
30: static el_val_t __thunk_helper(void* __v) {
34: el_val_t helper(void) {

cc at bb040ad (0005, exit 1) reports, in this order:

mod_pre.c:25:17: error: redefinition of '__el_body_helper'
mod_pre.c:29:8:  error: redefinition of '__env_helper'
mod_pre.c:30:17: error: redefinition of '__thunk_helper'
mod_pre.c:34:10: error: redefinition of 'helper'

Four errors. The user's own function is the fourth. The first three name symbols the user never wrote. Exact match, including order.

A6 / A11 — the repair, and its stated limit

At 79f6cb7 the collision is caught at El level from recorded relations (0006, checker exit 1):

duplicate definition: 'helper' is defined 2 times — El has no namespacing, so imported modules share one global scope

verbatim to the record. And the limit is visible in the same output: it names which name collides and not which files, because by the time codegen runs resolve_imports has produced one source string. That limit is what cycle 16 goes on to remove.

A1 — the mechanism, verbatim from source

0016, compiler.el at 79f6cb7:

416:fn resolve_imports(src_path: String) -> String {
417:    let seen_key: String = "__elc_imp__:" + src_path
420:    state_set(seen_key, "1")
455:    let imp_elh_path: String = str_slice(imp_path, 0, str_len(imp_path) - 3) + ".elh"
456:    let imp_elh: String = fs_read(imp_elh_path)
457:    if !str_eq(imp_elh, "") {
460:        let seen_imp_key: String = "__elc_imp__:" + imp_path
461:        state_set(seen_imp_key, "1")
462:        let prefix_chunks = native_list_append(prefix_chunks, imp_elh)

Textual inlining; __elc_imp__:<path> as the double-inclusion guard; header preferred over body and the .el marked seen. Every clause of A1 and A2 present in the code, and demonstrated in behaviour by the AF chain.

Suite results at 79f6cb7

104 tests, 104 passed, 0 failed, 249 assertions      (0009)
4 assertions, 4 passed, 0 failed  definitions_query  (0007)
FIXPOINT-OK  gen2 == gen3                            (0008)
definitions: clean   exit=0   (compiler's own source) (0017)

All four figures match the record.

Provenance notes

Every artifact in this cycle was captured from a dedicated worktree — /tmp/rerun-v1b-15-pre (bb040ad) or /tmp/rerun-v1b-15-post (79f6cb7) — with capture.sh invoked by absolute path from inside it, so the recorded commit is the system under test's, and fixtures and build products were kept outside the worktree so the tree stayed clean. No DIRTY-TREE flags in this cycle; every artifact is reproducible by checking out its recorded commit.

One capture (0013) was taken a first time with the working directory left in the shared main checkout, which recorded the wrong commit. It was deleted, its manifest row removed, and the measurement re-run from inside the worktree. The result was unchanged.