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
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

15 KiB
Raw Permalink Blame History

CLAIMS — cycle 04, c has no closure syntax

Source doc: docs/v1/experiments/cycles/04-c-has-no-closure-syntax.md

Pinned commits

Cycle commit (the EXPERIMENT) 2bed8483f75ebc76eefac69567b01d2da70d5db9
Committed 2026-08-17 08:08:37 -0500
Subject EXPERIMENT: hand the construct the body as a real closure
Parent (the "before" state) 4f7568b07f61a81fed1db5b8274813032ea3b16e
Land commit 7d01608a9dd3f7d4f6f476f567504d3ec341e7af
Committed 2026-08-17 08:12:16 -0500
Subject land wraps_body: a construct controls invocation
Land parents 4f7568b (first) + 2bed848 (second) — an ordinary merge
Re-run method detached worktrees /tmp/rerun-v1-04a at 2bed848 and /tmp/rerun-v1-04b at 7d01608, both trees clean
Artifact provenance every artifact pinned to 2bed8483f75e or 7d01608a9dd3, tree clean (see MANIFEST.tsv)
Machine Wills-MacBook-Pro, Darwin 25.5.0 arm64, Apple clang 21.0.0 (see RUN.env)

git diff 2bed848 7d01608 is empty (0050): the land commit's tree is byte-for-byte the experiment's tree. Everything measured at 2bed848 therefore also holds at 7d01608; the 04b captures confirm it independently.

The only file the cycle touches is lang/el-compiler/src/codegen.el (+134 / 3, net +131). Line count 4f7568b = 49532bed848 = 5084 (0050), consistent with the net delta.

Verdicts

# Claim (verbatim from the record) Artifact Commit Verdict
1 P1 "env struct + thunk taking void* — TRUE" 0008, 0009 2bed848 REPRODUCED — emitted C contains struct __env_base { el_val_t n; };, static el_val_t __thunk_base(void* __v), and extern el_val_t twice_and_sum(el_val_t, el_val_t, el_val_t(*)(void*), void*);
2 P2 "fails to compile: struct redefinition — FALSE" 0015, 0010, 0011 2bed848 REPRODUCED — no redefinition failure. The env structs are file-scope and uniquely named per fn (__env_base, __env_never_runs; four distinct tags in the 4-fn probe). A 2-wrap and a 4-wrap translation unit each compile and link clean.
3 P2 reason: "C allows the inner declaration to shadow" 0018, 0015 2bed848 NOT-CAPTURED as an account of this emitter — the C language fact is confirmed independently (0018: a block-scope struct E shadows a file-scope struct E, cc -std=c11 -Wall -Wextra exit 0, prints outer=3 inner=7). But the emitter at 2bed848 emits no inner/block-scope struct declaration at all, so nothing shadows anything. The intermediate emitter that would have produced the shadowed declaration exists in no commit and cannot be measured.
4 P2 real defect: "a wrap with no exit construct emitted (EL_STR("f"), EL_STR(""), __r); — a call to an empty target … Fixed." 0016, 0017 2bed848, 4f7568b REPRODUCED (defect absent, fix present) — grep for EL_STR("") in the emitted C of a wrap-with-no-exit program returns exit 1 (absent). Mechanism confirmed: at the parent 4f7568b the exit line is emitted unconditionally (codegen.el:3360); at 2bed848 it is guarded by if !str_eq(exit_target, "") (codegen.el:3458) and has_exit is widened to !str_eq(exit_target, "") || has_wrap (3405), exactly as the record describes.
5 P3 "compiles when the target is declared in El — FALSE" 0013, 0014 2bed848 REPRODUCEDelc accepts the El extern fn, then cc fails with 3 errors: conflicting types for 'twice_and_sum', and two incompatible pointer to integer conversion (passing el_val_t (void *) and struct __env_base * to parameters of type long long). cc_rc=1.
6 P3 "El has ONE type, el_val_t = int64_t" 0006, 0057 2bed848 REPRODUCEDtypedef int64_t el_val_t; at lang/runtime/el_runtime.h:50, el_seed.h:32, el_native_target.h:26. Erasure confirmed: fn mixed(a: Int, b: String, c: Bool) -> Int emits el_val_t mixed(el_val_t a, el_val_t b, el_val_t c).
7 P3 "codegen DEFINES the wrap calling convention, so codegen emits the extern declaration" 0008, 0009, 0017 2bed848 REPRODUCED — codegen.el:3442 emits the extern el_val_t <target>(el_val_t, el_val_t, el_val_t(*)(void*), void*); line; it appears in the emitted C at line 22/38.
8 P4 "target controls invocation, 0..N times — TRUE" 0011, 0012, 0010 2bed848 REPRODUCED — one El source, four wrap targets differing only in how many times they call the thunk: 0 → 999, 1 → 5, 2 → 10, 3 → 15.
9 P5 "existing @manager output byte-identical — TRUE" 0019, 0020, 0028, 0038 4f7568b vs 2bed848 REPRODUCED — the parent compiler was rebuilt from a git archive 4f7568b extraction (0019) and the same inputs compiled with both emitters. All 3 files in the tree that apply @manager/@accessor (engram/src/server.el 1 application, tools/api-reshape/route_proof.el 7, tools/api-reshape/surface.el 8) emit byte-identical C. Treewide: 378 .el files → 368 identical, 1 byte-differing, 9 failing under both emitters. The 1 differing file is explained below and is not caused by this cycle.
10 P6 "compiler fixpoint holds — TRUE" 0051, 0054 2bed848, 7d01608 REPRODUCED — gen2 == gen3 at both commits; at these commits gen1 == gen2 as well, so all three generations share sha256 91b3de5b5c95cc659fb4d78aa821627c9a5c325c14b461852efff7db3f68a64b.
11 P7 "emitting the convention makes it compile — TRUE" 0010, 0055 2bed848, 7d01608 REPRODUCEDCOMPILE_AND_LINK_OK at both commits, against a C translation unit supplying the two wrap targets.
12 MEASURED "base(5) wrapped by a target that invokes the body twice and sums -> 10" 0007, 0010, 0055 2bed848, 7d01608 REPRODUCED — via a RECONSTRUCTED probe (see below) — observed base(5) = 10
13 MEASURED "never_runs(5) wrapped by a target that never invokes it -> 999" 0007, 0010, 0055 2bed848, 7d01608 REPRODUCED — via a RECONSTRUCTED probe (see below) — observed never_runs(5) = 999
14 "This supersedes the repeats_body experiment on experiment/repeats-body" 0049 all refs DIVERGED — no such ref exists. See below.
15 7d01608: "Proven on experiment/wraps-body (2bed848)" 0049 all refs DIVERGED — no such ref exists. The commit 2bed848 is present and reachable; the branch name is not.
16 "Every C++ lambda, every Go closure, every Rust closure compiles to a struct of captured values plus a function pointer" 0008, 0009 NOT-CAPTURED — the trailing half, "which is what is emitted here", is claim 1 and is REPRODUCED. The claim about C++/Go/Rust codegen is about three other toolchains, none of which is in this tree; it was not measured then and is out of scope for this record.
17 "It would also have crippled the JS backend, which has closures natively, for a limit that applies only to the C one" 0058 2bed848 NOT-CAPTURED (counterfactual) — and the premise is weaker than stated: lang/el-compiler/src/codegen-js.el (1381 lines) implements no construct machinery whatsoever at 2bed848. It contains no reference to wraps_body, injects_at_entry, guards_at_entry, injects_at_exit, thunks or env structs; the only decorator it knows is @async (line 1119). There is no wrap emission in the JS backend to cripple, either way.

Counts: 13 REPRODUCED · 2 DIVERGED · 0 NOT-REPRODUCIBLE · 2 NOT-CAPTURED (17 assertions).

The MEASURED numbers were produced by a RECONSTRUCTED probe

State plainly: no test, fixture, or harness in the tree at 2bed848 exercises wraps_body. git grep wraps_body outside codegen.el returns exit 1; lang/tests/integration/ does not exist at either pinned commit (0056); and 2bed848 changes exactly one file, codegen.el, adding no test. The probe the commit message describes was never committed.

The probe was therefore reconstructed from what the record states, and it is an INPUT, not evidence. Its full text is in the record at 0007:

  • w04.el — two declared wrap constructs (@decorator("wraps_body", "twice_and_sum") and @decorator("wraps_body", "never_invoke")) applied to base(n) and never_runs(n), both bodies return n, with main printing base(5) and never_runs(5).
  • targets04.c — the two wrap targets, which cannot be written in El (that is claim 5): twice_and_sum returns body(env) + body(env); never_invoke ignores the body and returns 999.

The artifact is the captured output of running it at the pinned commits (0010 at 2bed848, 0055 at 7d01608), which reads:

COMPILE_AND_LINK_OK
base(5) = 10
never_runs(5) = 999

The emitted C is byte-identical between 2bed848 and 7d01608 (0055).

Reconstruction risk, stated honestly: the record fixes the inputs (5), the target semantics ("invokes the body twice and sums", "never invokes it") and the outputs (10, 999), and the 999 sentinel is only reachable from the target, so it is not a value the body could have produced. What the record does not fix is the target's names, which are free choices here. The numbers were observed, not asserted.

Divergence detail — claims 14 and 15, the two branch references

Both pinned records point at branches that are not in the clone (0049):

  • git branch -a --list '*repeats-body*'no output, exit 0
  • git branch -a --list '*wraps-body*'no output, exit 0
  • git for-each-ref | grep -i bodyno matching ref of any kind
  • git log --all --oneline --grep=repeats_body and --grep=repeats-body → the only match is 2bed848 itself, i.e. the sentence making the claim
  • 249 branches exist in the clone; none of them is either name.

Consequences, and they are not symmetrical:

  • Claim 15 (7d01608: "Proven on experiment/wraps-body (2bed848)") is a cosmetic divergence. The branch is gone but the commit it names survives, is reachable, and everything it asserts re-measures. Only the branch label is wrong.
  • Claim 14 ("This supersedes the repeats_body experiment on experiment/repeats-body, which was built around the mistaken limit") is a substantive one. The superseded work is unrecoverable: no branch, no tag, no commit anywhere in the object graph mentions repeats_body. The record's central rhetorical move — that a strictly weaker "decide whether to repeat" design existed, was built, and was replaced — rests entirely on a dangling reference. That the weaker design is weaker is separately demonstrable (claim 8 shows 0 and 3 invocations, neither expressible as "repeat or not"), but the existence and content of the superseded experiment cannot be checked from this repository.

Supporting finding — the one treewide byte-difference is pre-existing nondeterminism

The treewide P5 sweep (0028) found exactly one file whose emitted C differs between the parent and the commit: arbor/vessels/arbor-parse/src/main.el. It is not a regression from this cycle (0038):

  • The file applies zero decorators (grep -c '^@' = 0), so no construct machinery — wrap or otherwise — is reachable in it.
  • Two consecutive runs of the same compiler at 2bed848 produce different output.
  • Two consecutive runs of the same compiler at the parent 4f7568b also produce different output.

The difference is always the same three lines, where a string literal is emitted as a large decimal number that changes run to run (e.g. EL_STR("40345588256") vs EL_STR("30447047200") at line 325, and similarly at 338 and 392) — an address, or an address-derived value, leaking into the emitted literal. This is a real pre-existing emitter defect worth its own investigation, but it predates cycle 04 and does not touch claim 9.

The 9 files that fail under both emitters (identical exit codes, 0028) are likewise unchanged by the cycle: arbor-core/src/main.el, arbor-render/src/main.el, elp/src/vocabulary-{de,fr,it,pt,ro}.el, ui/examples/native-hello/src/{App,main}.el.

Measurements the record makes no claim about, recorded as observed

The cycle doc states no test count, no fixpoint detail and no timing. Observed:

  • Native compiler tests: 98 tests, 98 passed, 0 failed, 243 assertions at 2bed848 (0004, 5.660ms) and the same 98/98/0/243 at 7d01608 (0053, 6.297ms). No failures at either commit.
  • Stage2 build: BUILD_OK, generated elc-cli.el C = 11494 lines at both commits (0003, 0052).
  • lang/tests/integration/ does not exist at either pinned commit (0056), so no integration harness could be run. lang/tests/ contains bench, calendar, html_sanitizer, native, runtime, suite, swarm, text, time.
  • codegen.el: 4f7568b 4953 → 2bed848 5084 → 7d01608 5084 (0050).

Measurement defects in this re-run, recorded rather than removed

Defect 1 — superseded fixpoint command (recipe defect, not this cycle's). Artifact 0005-selfhost-fixpoint-04a.out was captured with the recipe's original command, which compares gen1 (the committed dist/platform/elc's output) against gen2. That is the wrong check: gen1 may legitimately differ from gen2 whenever codegen's output changes, and reporting it as a break would be a fabricated divergence. The corrected three-generation check (gen2 == gen3) is 0051 at 2bed848 and 0054 at 7d01608. 0005 is retained, not deleted. It happens to agree — at these commits gen1 == gen2 too — but it should not be cited as the fixpoint evidence.

Defect 2 — multi-line commands corrupted MANIFEST.tsv line structure. Four captures (0020, 0028, 0038, and the shell text of 0019) were invoked with bash -c scripts containing literal newlines. capture.sh writes the command verbatim as the last TSV field, so those newlines became extra physical lines in MANIFEST.tsv. Two visible consequences:

  • the artifact counter, which is derived from the manifest's line count, jumped (0020002800380049), so the artifact numbers in this cycle are not contiguous. No artifact is missing; the gaps are counter skips.
  • MANIFEST.tsv is no longer strictly one physical line per artifact.

verify-manifest.sh is unaffected — the continuation lines parse with an empty artifact field and are skipped — and the cycle verifies 0 altered, 0 missing with every row clean. The manifest was not edited to tidy this up; editing it is precisely the defect this record exists to control for. Later captures use single-line commands.

Reproduction

git worktree add /tmp/rerun-v1-04a 2bed848
git worktree add /tmp/rerun-v1-04b 7d01608

then the commands in MANIFEST.tsv, and bash tools/evidence/verify-manifest.sh docs/v1/experiments/evidence/cycles. The parent compiler used for claim 9 is built by 0019 from a git archive 4f7568b extraction into /tmp/p04parent; no worktree at the parent is required.