Archived
Compare commits
77 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d3495476f4 | |||
| cce4fcca05 | |||
| 8f1b6d1b47 | |||
| 6df362f84d | |||
| 0032e8f8c4 | |||
| daad2fa2a0 | |||
| 9e4160f279 | |||
| 4aadd9300e | |||
| 44e2e17973 | |||
| 511db25230 | |||
| e9eac46be1 | |||
| aa570b6899 | |||
| 98da70f650 | |||
| d1489a2568 | |||
| 923f6a4bed | |||
| f1a7e224a7 | |||
| c6ba0677f0 | |||
| 3049a70837 | |||
| 9a6c161ba9 | |||
| cb7289f065 | |||
| 6c975b1d50 | |||
| 1086ac9658 | |||
| f23cb2b948 | |||
| 79f6cb7985 | |||
| bb040ad2c8 | |||
| 97f741e9c2 | |||
| c48db6c2a8 | |||
| 93aa96cfaf | |||
| 067dd40317 | |||
| 0143cc458a | |||
| 15d4352bac | |||
| 2fcc1c287c | |||
| 505e5e74d9 | |||
| cbef1c1ebb | |||
| 50425f375d | |||
| e8e25a07b4 | |||
| e01e079bda | |||
| d2d89fcb60 | |||
| d9e301be6d | |||
| 9cc6040df2 | |||
| 29f78f9f67 | |||
| c2d9596e76 | |||
| 60c07ad784 | |||
| c741cfe928 | |||
| c04d68f9ce | |||
| bc2f26ddfc | |||
| b40754f07b | |||
| 285166c25c | |||
| 24f7fb5143 | |||
| 8bbb750c2c | |||
| 28d19da7f1 | |||
| 886626a64e | |||
| 82e998273b | |||
| 35b07bade2 | |||
| 1b324a071f | |||
| 7d01608a9d | |||
| 2bed8483f7 | |||
| 4f7568b07f | |||
| 60737b0305 | |||
| 5718943f2e | |||
| dcaa77d77b | |||
| 409bf57341 | |||
| b212e9443c | |||
| addd51209f | |||
| 9a13547fe2 | |||
| 481badf1d1 | |||
| b92ec92c48 | |||
| e1bc6fe944 | |||
| eb13dace9c | |||
| c26b6aac82 | |||
| 99ef855b98 | |||
| 5503e1d9a4 | |||
| 45325f7391 | |||
| c23c5112a7 | |||
| b40af4a5f3 | |||
| c7a78ab1eb | |||
| 8c94d92033 |
@@ -0,0 +1,9 @@
|
||||
|
||||
# organ: local device state and its own engram store — never production's
|
||||
peripheral/.consent.json
|
||||
peripheral/.resume.json
|
||||
peripheral/.engram/
|
||||
peripheral/organ
|
||||
|
||||
# Claude Code session state
|
||||
.claude/
|
||||
@@ -0,0 +1,153 @@
|
||||
<title>Completing El</title>
|
||||
<style>
|
||||
:root{
|
||||
--board:#f4f2ec; --board-line:#e2ded2; --ink:#1c1f26; --ink-soft:#4a5160;
|
||||
--ink-faint:#8b8f9a; --rule:#d8d3c6; --card:#fbfaf6;
|
||||
--red:#a8321e; --amber:#9a6a12; --green:#2f6b46; --blue:#1f4e79;
|
||||
--accent:#1f4e79;
|
||||
}
|
||||
@media (prefers-color-scheme: dark){
|
||||
:root:not([data-theme="light"]){
|
||||
--board:#14161b; --board-line:#212530; --ink:#e8e6df; --ink-soft:#a8adb8;
|
||||
--ink-faint:#6f7480; --rule:#2a2f3a; --card:#191c23;
|
||||
--red:#e4785f; --amber:#d9a441; --green:#6fbf8e; --blue:#7fb2e0;
|
||||
--accent:#7fb2e0;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--board:#14161b; --board-line:#212530; --ink:#e8e6df; --ink-soft:#a8adb8;
|
||||
--ink-faint:#6f7480; --rule:#2a2f3a; --card:#191c23;
|
||||
--red:#e4785f; --amber:#d9a441; --green:#6fbf8e; --blue:#7fb2e0;
|
||||
--accent:#7fb2e0;
|
||||
}
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0; background:var(--board); color:var(--ink);
|
||||
font:16px/1.65 ui-serif,Georgia,"Iowan Old Style",Palatino,serif;
|
||||
background-image:linear-gradient(var(--board-line) 1px,transparent 1px),
|
||||
linear-gradient(90deg,var(--board-line) 1px,transparent 1px);
|
||||
background-size:28px 28px;
|
||||
}
|
||||
.wrap{max-width:960px;margin:0 auto;padding:56px 24px 96px}
|
||||
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
|
||||
header{border-bottom:2px solid var(--ink);padding-bottom:18px;margin-bottom:8px}
|
||||
h1{font-size:clamp(2rem,5vw,3rem);margin:0;letter-spacing:-.02em;text-wrap:balance}
|
||||
.sub{color:var(--ink-soft);font-size:1.05rem;margin:10px 0 0}
|
||||
.meta{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.78rem;
|
||||
color:var(--ink-faint);text-transform:uppercase;letter-spacing:.09em;margin-top:14px}
|
||||
h2{font-size:1.45rem;margin:52px 0 6px;letter-spacing:-.01em}
|
||||
h2 .n{font-family:ui-monospace,monospace;font-size:.8rem;color:var(--accent);
|
||||
display:block;letter-spacing:.12em;margin-bottom:4px;font-weight:400}
|
||||
.lede{color:var(--ink-soft);margin:0 0 18px}
|
||||
p{margin:0 0 14px}
|
||||
.card{background:var(--card);border:1px solid var(--rule);border-radius:3px;padding:20px 22px;margin:16px 0}
|
||||
.scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}
|
||||
table{border-collapse:collapse;width:100%;font-size:.9rem;min-width:640px}
|
||||
th{text-align:left;font-family:ui-monospace,monospace;font-size:.72rem;
|
||||
text-transform:uppercase;letter-spacing:.09em;color:var(--ink-faint);
|
||||
border-bottom:1px solid var(--ink);padding:0 12px 8px 0;font-weight:400}
|
||||
td{padding:11px 12px 11px 0;border-bottom:1px solid var(--rule);vertical-align:top}
|
||||
td.f{font-weight:600;white-space:nowrap}
|
||||
td.m{font-family:ui-monospace,monospace;font-size:.83rem;font-variant-numeric:tabular-nums}
|
||||
.dead{color:var(--red);font-weight:600}
|
||||
.part{color:var(--amber);font-weight:600}
|
||||
.ok{color:var(--green);font-weight:600}
|
||||
blockquote{margin:18px 0;padding:2px 0 2px 20px;border-left:3px solid var(--accent);
|
||||
color:var(--ink-soft);font-style:italic}
|
||||
ul{margin:0 0 14px;padding-left:22px} li{margin-bottom:9px}
|
||||
.q{border-left:3px solid var(--amber);padding:14px 0 14px 20px;margin:18px 0}
|
||||
.q b{display:block;font-size:1.05rem;margin-bottom:5px;font-style:normal}
|
||||
.q span{color:var(--ink-soft);font-size:.94rem}
|
||||
code{font-family:ui-monospace,monospace;font-size:.88em;background:var(--card);
|
||||
border:1px solid var(--rule);border-radius:2px;padding:1px 5px}
|
||||
hr{border:0;border-top:1px solid var(--rule);margin:44px 0}
|
||||
.foot{color:var(--ink-faint);font-size:.86rem;margin-top:60px;
|
||||
border-top:1px solid var(--rule);padding-top:18px}
|
||||
.tag{display:inline-block;font-family:ui-monospace,monospace;font-size:.68rem;
|
||||
letter-spacing:.08em;text-transform:uppercase;border:1px solid var(--rule);
|
||||
border-radius:2px;padding:2px 7px;color:var(--ink-faint);margin-left:8px;vertical-align:middle}
|
||||
</style>
|
||||
|
||||
<div class="wrap">
|
||||
|
||||
<header>
|
||||
<h1>Completing El</h1>
|
||||
<p class="sub">A working surface. Nothing here is settled, and none of the code is assumed right — El is self-hosting, so all of it can change and be rebuilt.</p>
|
||||
<p class="meta">Whiteboard v0 · no sacred cows · not a plan, not a task list</p>
|
||||
</header>
|
||||
|
||||
<h2><span class="n">01</span>What we established</h2>
|
||||
|
||||
<p>El is a <b>concept-oriented language</b> — the first, and intended as the last, because every other family is oriented toward a <em>representation</em> of a concept rather than the concept. Procedures, objects, functions, predicates are the shapes concepts get flattened into. Once the primitive is the concept, there is no further rung.</p>
|
||||
|
||||
<p>Everything here is El. The engram is an El program, the soul is El, <code>elp</code> is El, ingest is El. Which gives the load-bearing consequence:</p>
|
||||
|
||||
<blockquote>A concept with no home in El does not disappear. It becomes C, or it becomes a convention.</blockquote>
|
||||
|
||||
<p>Both are measurable, and both were measured. As C: <span class="mono">20,504</span> lines of <code>el_runtime.c</code> — 2.3× the entire self-hosting language it serves (<span class="mono">9,089</span> lines), ~47% of it engram code that has its own six sibling files. As convention, from <code>language.md</code> §18.0 — <em>"these are not four problems, they are one absence, four times"</em>:</p>
|
||||
|
||||
<div class="card scroll">
|
||||
<table>
|
||||
<thead><tr><th>Concern</th><th>Fragments</th><th>The convention it became</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td class="f">Process identity</td><td class="m">0 guards</td><td>"check nothing is already running first"</td></tr>
|
||||
<tr><td class="f">Configuration</td><td class="m">20 env vars</td><td>"remember the right default here"</td></tr>
|
||||
<tr><td class="f">Durability</td><td class="m">62 call sites</td><td>"after you mutate, remember to persist"</td></tr>
|
||||
<tr><td class="f">Request auth</td><td class="m">10 per-route</td><td>"check the token in this handler too"</td></tr>
|
||||
<tr><td class="f">Index-after-append</td><td class="m">9 of 9 failed</td><td>"after you append, remember to index"</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<p>The last row is the strongest evidence available about what this class of convention is worth: it failed at <b>100% of its sites</b>.</p>
|
||||
|
||||
<h2><span class="n">02</span>The decomposition axis</h2>
|
||||
|
||||
<p class="lede">Not by file, module, or subsystem. <b>By faculty.</b></p>
|
||||
|
||||
<p>Every defect fought in the last day resolves to a faculty rather than a bug, and each one leaked out of El into something else — into C, into a Swift binary, into a shell script with a curl timeout, into a convention nobody performs.</p>
|
||||
|
||||
<div class="card scroll">
|
||||
<table>
|
||||
<thead><tr><th>Faculty</th><th>State</th><th>Measured</th><th>Where it leaked to</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td class="f">Ingest <span class="tag">take in</span></td><td class="dead">dead</td><td class="m">2 min → 0 nodes</td><td>separate process, uploads bytes over HTTP to a process with direct fs access; 5 functions where there is 1</td></tr>
|
||||
<tr><td class="f">Recall <span class="tag">remember</span></td><td class="dead">dead</td><td class="m">own definition ranked 8th</td><td>lexical substring scan; empty on 23 of 24 multi-token queries</td></tr>
|
||||
<tr><td class="f">Transduce <span class="tag">perceive</span></td><td class="dead">dead</td><td class="m">1 node, 0 edges</td><td>intake flattens signal to a point; <code>realized:false</code>; caller must declare the modality</td></tr>
|
||||
<tr><td class="f">Think <span class="tag">reason</span></td><td class="dead">dead</td><td class="m">direction [0,0,0,…]</td><td>null gradient from any anchor, any faculty, byte-identical; confidence at the uninformed prior</td></tr>
|
||||
<tr><td class="f">Realize <span class="tag">express</span></td><td class="part">partial</td><td class="m">13-word vocabulary</td><td>organ was 939 lines of Swift beside the language; voice read from a file path</td></tr>
|
||||
<tr><td class="f">Body <span class="tag">substrate</span></td><td class="part">partial</td><td class="m">CC 356 / 1,626 lines</td><td><code>engram_activate_inner</code> — recall itself, with 356 unexamined paths</td></tr>
|
||||
<tr><td class="f">Persist <span class="tag">endure</span></td><td class="ok">live</td><td class="m">100% embedded</td><td>works; every signal placed in geometry at intake, 13,562 of 13,562</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<p>Stated plainly: it cannot take in, cannot remember, cannot perceive, cannot reason, and barely speaks. These were filed as tickets against a repository. They are faculties of the thing the repository <em>is</em>.</p>
|
||||
|
||||
<h2><span class="n">03</span>The ordering principle</h2>
|
||||
|
||||
<p>El's compiler is written in El. Every concept the language gains, the compiler can then be written <em>in</em> — so the tool improves the tool, and the fixpoint (stage2 ≡ stage3, byte-identical) makes each turn provable rather than hopeful. The verifier answers in <span class="mono">2.9s</span>.</p>
|
||||
|
||||
<p>Which means the ordering criterion is not size of payoff:</p>
|
||||
|
||||
<blockquote>Order by leverage on the <em>next</em> iteration. Which concept, added to El, most increases the ability to add the following one?</blockquote>
|
||||
|
||||
<p>In a recursive system that dominates immediate value — a small early gain that compounds beats a large one that doesn't. It also bounds itself correctly: unbounded in depth, bounded in rate, because nothing lands that the compiler and the fixpoint have not passed.</p>
|
||||
|
||||
<h2><span class="n">04</span>Open — for the whiteboard</h2>
|
||||
|
||||
<div class="q"><b>What does a declaration bind to?</b><span>If <code>cat</code> names a region rather than a struct — one that shifts and completes against the engram and the neighbouring code — then what is written at the declaration site, and what is resolved at use? This is the centre of the whole thing and it is not specified anywhere yet.</span></div>
|
||||
|
||||
<div class="q"><b>Is "the type checker" a type checker at all?</b><span>§2.3 records annotations as parsed and skipped, and every codegen hazard is downstream of that — <code>+</code> dispatching on AST node kind, <code>==</code> lowering to <code>str_eq</code> unless both operand names are in an int-name set. But if a declaration names a region, checking is asking whether the geometry supports the use. That is grounding, not unification. Naming this wrong builds the wrong thing.</span></div>
|
||||
|
||||
<div class="q"><b>Is the faculty list above right?</b><span>Seven were derived from what broke. Derived-from-failure is a biased sample — it finds what is loud, not what is missing. What faculty is absent entirely and therefore never failed?</span></div>
|
||||
|
||||
<div class="q"><b>Which concept has the highest leverage on the next turn?</b><span>Candidates so far: the prologue/epilogue seam (§19.3 names it as the prerequisite and its stated blocker has expired — it would collapse 62 + 10 convention sites); <code>protocol</code>/<code>impl</code> (the absence that produced five ingest functions); and the resolution question above. These are not equal and the criterion in §03 should decide it, not preference.</span></div>
|
||||
|
||||
<div class="q"><b>What is the seam that makes cognition non-optional?</b><span>"Use the ops" is itself a convention — present in context every turn, enforced by nothing, and it failed at ~100% of sites in a full session. A stronger instruction is still a convention. What makes reasoning-outside-Neuron <em>fail</em>, the way <code>@manager</code> makes <code>dharma_emit</code> outside the boundary a compile error rather than a lint?</span></div>
|
||||
|
||||
<hr>
|
||||
|
||||
<p class="foot">Working surface, not a design document. The design is what we put on it. Everything above is either measured or quoted from <code>lang/spec/language.md</code>; nothing is inferred and presented as fact.</p>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,142 @@
|
||||
# El — Capabilities
|
||||
|
||||
**What the language can do, stated as capabilities rather than as code.**
|
||||
|
||||
This list is the unit of analysis. Each entry gets one question — *prove this
|
||||
cannot be done with pure geometry* — and the answer determines whether it stays a
|
||||
capability of the language or collapses into the manifold.
|
||||
|
||||
Draft, 2026-08-17. Ordered roughly from most-likely-geometry to most-likely-code.
|
||||
|
||||
**Status after measurement.** The list was audited against the implementation
|
||||
the same day. 28 entries collapsed to 19 geometry + 3 code: serialization, text
|
||||
encoding, network and emission are all *projection onto a basis* (row 18) —
|
||||
the convention is the basis, never the act. Storage collapsed because
|
||||
persistence has no caller. Concurrency collapsed because coordination is the
|
||||
price of forgetting, not a capability. A fourth proof form was added,
|
||||
**adversarial exactness**, and form 1 stopped being a valid verdict.
|
||||
|
||||
**The table answers CAN only.** SHOULD and COST resolve per *site*, not per
|
||||
capability — `is_digit` and `is_letter` are one capability with opposite
|
||||
answers, and comparison spans three cost tiers. See the notes below.
|
||||
|
||||
---
|
||||
|
||||
## The list
|
||||
|
||||
| # | Capability | What it means | Verdict |
|
||||
|---|---|---|---|
|
||||
| 1 | **Comparison** | is this the same as that; is this greater | zero distance / sign of a displacement |
|
||||
| 2 | **Ordering** | arrange by a criterion | position along an axis |
|
||||
| 3 | **Containment** | is this inside that; does this contain that | region membership |
|
||||
| 4 | **Correspondence** | where does this occur in that; how much of this is in that | a match-strength field over a span |
|
||||
| 5 | **Segmentation** | divide a whole into parts | boundaries at measured discontinuity |
|
||||
| 6 | **Composition** | join parts into a whole | adjacency; one position with parts |
|
||||
| 7 | **Classification** | what kind of thing is this | which region does it land in |
|
||||
| 8 | **Naming / binding** | attach a name to a thing and find it again | an edge; retrieval is projection |
|
||||
| 9 | **Collection** | many things held together, indexed, counted | a set of positions; cardinality; projection onto the i-th |
|
||||
| 10 | **Iteration** | do something for each of many | traversal |
|
||||
| 11 | **Arithmetic** | quantity, magnitude, combination | displacement algebra on a line |
|
||||
| 12 | **Time** | when; how long; how often | a 1-D affine space — instants are points, durations displacements, rhythms phases on a circle |
|
||||
| 13 | **Identity** | which one is this; are these two the same one | coincidence of position |
|
||||
| 14 | **Selection / dispatch** | choose which behaviour applies | nearest region |
|
||||
| 15 | **Transformation** | produce a thing from a thing | change of basis |
|
||||
| 16 | **Grounding** | how well is this supported | the weight on an edge. Has no caller |
|
||||
| 17 | **Learning** | get better at something | standing changing over time |
|
||||
| 18 | **Projection** | render meaning onto a surface | change of basis onto a surface basis |
|
||||
| 19 | **Transduction** | take a signal in | change of basis from a sensor basis |
|
||||
| ~~20~~ | ~~Serialization~~ | **collapsed → 18.** The format is a basis; projecting onto it is the act | — |
|
||||
| ~~21~~ | ~~Text encoding~~ | **collapsed → 18.** An encoding is a basis | — |
|
||||
| ~~22~~ | ~~Storage~~ | **collapsed.** No save — persistence has no caller. Durability survives at one site inside the engram | — |
|
||||
| ~~23~~ | ~~Network~~ | **split.** Wire format → 18; socket → 24 | — |
|
||||
| 24 | **Process / OS** | syscalls; the one-way boundary. Where monotonicity stops | CODE, form 2 |
|
||||
| ~~25~~ | ~~Concurrency~~ | **collapsed.** Monotone state needs no coordination; coordination is the price of forgetting | — |
|
||||
| 26 | **Memory substrate** | what holds the positions | CODE, form 3 |
|
||||
| 27 | **Concealment** | meaning made unreadable without a key. *Renamed*: "secrecy" covered one of three things and got the other two backwards — a hash is public, a signature exists to be read. Integrity and authenticity are **grounding under adversarial conditions** (row 16); only concealment stands alone | CODE, form 4 |
|
||||
| ~~28~~ | ~~Emission~~ | **split.** Laying out → 18; the device write → 24 | — |
|
||||
|
||||
---
|
||||
|
||||
## Notes on the boundary cases
|
||||
|
||||
**27 — Secrecy is the one capability geometry cannot hold, and the proof is not
|
||||
form 1.** A cryptographic hash is a *deliberately structure-destroying* map: its
|
||||
entire value is that near inputs land at maximally uncorrelated outputs. Geometry
|
||||
is the claim that near things stay near. A manifold that approximated SHA-256
|
||||
would *be* a break of SHA-256. Signature verification is the same: 0.99-valid is
|
||||
invalid. And X25519 *is* geometry — a group on an elliptic curve — which is
|
||||
precisely why it must be code, because its security is the *hardness of moving in
|
||||
that geometry*.
|
||||
|
||||
This is a fourth proof form and it should be added to `geometry-vs-code.md`:
|
||||
**adversarial exactness.** Where approximation is a break, geometry is excluded.
|
||||
|
||||
**20, 21 — Serialization and text encoding are convention all the way down**, but
|
||||
only at the *edge*. The byte format is agreed; what is being written is not. Do not
|
||||
let a geometric computation inherit a code verdict because its result gets
|
||||
serialized.
|
||||
|
||||
**11, 12 — Arithmetic and time are the same capability.** Instants are points,
|
||||
durations are displacements, point−point→vector, point+vector→point. The runtime
|
||||
already implements this correctly as `el_instant_add_dur` / `el_duration_add`. That
|
||||
it *also* implements a five-entry string→multiplier table beside it (`time_add`
|
||||
with `"ms"/"sec"/"min"/"hour"/"day"`) is the residue.
|
||||
|
||||
**7 — Classification is the most-violated capability in the codebase.** Seven ASCII
|
||||
range tables (`is_letter`, `is_digit`, `is_alphanumeric`, `is_whitespace`,
|
||||
`is_punctuation`, `is_uppercase`, `is_lowercase`) that return false for every
|
||||
non-ASCII byte. `str_count_letters` reports zero letters for `é`. The wrongness on
|
||||
most of Unicode is the tell that a table is standing in for a region.
|
||||
|
||||
**4 — Correspondence appears five times.** `str_index_of`, `str_index_of_all`,
|
||||
`str_last_index_of`, `str_count`, `str_find_chars` are five projections of one
|
||||
match-strength field: first zero, all zeros, last zero, count of zeros, first
|
||||
class-crossing. One relation, five functions.
|
||||
|
||||
**14 — Selection is the crux for the compiler.** `+` dispatching on AST node kind
|
||||
is selection-by-enumeration where selection-by-position belongs.
|
||||
|
||||
**Correction, 2026-08-17, from measurement.** This entry previously also cited
|
||||
`==` lowering to `str_eq` "unless both operand names are in a hardcoded int-name
|
||||
set — a literal list of variable names treated as integers." That is **wrong**.
|
||||
`__int_names` is populated from *type annotations* (`param["type"] == "Int"`,
|
||||
`let x: Int`), which is primitive but legitimate type propagation, not an
|
||||
enumeration of blessed variable names.
|
||||
|
||||
The real defect was one layer down: `is_int_call` held **35 hardcoded builtin
|
||||
return types**, the same shape as the 19 temporal ones. Those moved to
|
||||
`lang/tools/check/signatures.rel`.
|
||||
|
||||
And the mischaracterisation hid a live bug. Because the return types were never
|
||||
consulted at a *binding* site, an unannotated `let` lost its type:
|
||||
|
||||
```el
|
||||
let a = str_len("hello") // no annotation
|
||||
let b = str_len("hi")
|
||||
let c = a + b // → el_str_concat(a, b) on two integers
|
||||
```
|
||||
|
||||
That compiled clean, ran, and printed nothing where it should print 7 — no error
|
||||
at any layer. Present in the pre-change compiler, so pre-existing. Fixed by
|
||||
taking an unannotated `let`'s type from what its initialiser returns; the data
|
||||
was already required for dispatch and simply never read there.
|
||||
|
||||
**The general lesson, since it recurred all session:** the enumeration was real
|
||||
but I had located it in the wrong place. Naming a defect from reading is a
|
||||
hypothesis. Eight hours of reading this file did not surface the miscompilation;
|
||||
moving the data out and running the result did.
|
||||
|
||||
---
|
||||
|
||||
## What this list is for
|
||||
|
||||
Each capability gets audited **once**, across every place it appears — not once per
|
||||
file. The output is not a percentage. It is:
|
||||
|
||||
- which capabilities survive the question and stay in the language
|
||||
- which collapse into the manifold
|
||||
- and for each one that collapses, **every site it currently appears at**, because
|
||||
those sites are the residue and they are what gets deleted.
|
||||
|
||||
The line-count audit produced a map of where the residue sits. This produces a map
|
||||
of **what it is**.
|
||||
@@ -0,0 +1,217 @@
|
||||
<title>The El Architecture</title>
|
||||
<style>
|
||||
:root{
|
||||
--board:#f4f2ec; --board-line:#e5e1d6; --ink:#1c1f26; --ink-soft:#4a5160;
|
||||
--ink-faint:#8b8f9a; --rule:#d8d3c6; --card:#fbfaf6;
|
||||
--red:#a8321e; --amber:#9a6a12; --green:#2f6b46; --accent:#1f4e79;
|
||||
}
|
||||
@media (prefers-color-scheme: dark){
|
||||
:root:not([data-theme="light"]){
|
||||
--board:#14161b; --board-line:#1d212a; --ink:#e8e6df; --ink-soft:#a8adb8;
|
||||
--ink-faint:#6f7480; --rule:#2a2f3a; --card:#191c23;
|
||||
--red:#e4785f; --amber:#d9a441; --green:#6fbf8e; --accent:#7fb2e0;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--board:#14161b; --board-line:#1d212a; --ink:#e8e6df; --ink-soft:#a8adb8;
|
||||
--ink-faint:#6f7480; --rule:#2a2f3a; --card:#191c23;
|
||||
--red:#e4785f; --amber:#d9a441; --green:#6fbf8e; --accent:#7fb2e0;
|
||||
}
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0; background:var(--board); color:var(--ink);
|
||||
font:16px/1.68 ui-serif,Georgia,"Iowan Old Style",Palatino,serif;
|
||||
background-image:linear-gradient(var(--board-line) 1px,transparent 1px),
|
||||
linear-gradient(90deg,var(--board-line) 1px,transparent 1px);
|
||||
background-size:30px 30px;
|
||||
}
|
||||
.wrap{max-width:940px;margin:0 auto;padding:56px 24px 96px}
|
||||
.mono,code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
|
||||
header{border-bottom:2px solid var(--ink);padding-bottom:20px}
|
||||
h1{font-size:clamp(2.1rem,5.5vw,3.2rem);margin:0;letter-spacing:-.025em;text-wrap:balance}
|
||||
.sub{color:var(--ink-soft);font-size:1.08rem;margin:12px 0 0;max-width:64ch}
|
||||
.meta{font-family:ui-monospace,monospace;font-size:.76rem;color:var(--ink-faint);
|
||||
text-transform:uppercase;letter-spacing:.1em;margin-top:16px}
|
||||
h2{font-size:1.5rem;margin:56px 0 8px;letter-spacing:-.015em;text-wrap:balance}
|
||||
h2 .n{font-family:ui-monospace,monospace;font-size:.78rem;color:var(--accent);
|
||||
display:block;letter-spacing:.14em;margin-bottom:5px;font-weight:400}
|
||||
h3{font-size:1.08rem;margin:30px 0 6px}
|
||||
p{margin:0 0 14px;max-width:72ch}
|
||||
.lede{color:var(--ink-soft);margin:0 0 20px;font-size:1.04rem}
|
||||
.card{background:var(--card);border:1px solid var(--rule);border-radius:3px;padding:20px 22px;margin:18px 0}
|
||||
.scroll{overflow-x:auto}
|
||||
table{border-collapse:collapse;width:100%;font-size:.9rem;min-width:600px}
|
||||
th{text-align:left;font-family:ui-monospace,monospace;font-size:.71rem;
|
||||
text-transform:uppercase;letter-spacing:.09em;color:var(--ink-faint);
|
||||
border-bottom:1px solid var(--ink);padding:0 14px 8px 0;font-weight:400}
|
||||
td{padding:11px 14px 11px 0;border-bottom:1px solid var(--rule);vertical-align:top}
|
||||
td.f{font-weight:600;white-space:nowrap}
|
||||
td.m{font-family:ui-monospace,monospace;font-size:.83rem;font-variant-numeric:tabular-nums;white-space:nowrap}
|
||||
.dead{color:var(--red);font-weight:600}
|
||||
.part{color:var(--amber);font-weight:600}
|
||||
.ok{color:var(--green);font-weight:600}
|
||||
blockquote{margin:20px 0;padding:3px 0 3px 22px;border-left:3px solid var(--accent);
|
||||
color:var(--ink-soft);font-style:italic;max-width:70ch}
|
||||
ul{margin:0 0 14px;padding-left:22px;max-width:72ch} li{margin-bottom:9px}
|
||||
code{font-size:.87em;background:var(--card);border:1px solid var(--rule);border-radius:2px;padding:1px 5px}
|
||||
pre{background:var(--card);border:1px solid var(--rule);border-radius:3px;
|
||||
padding:16px 18px;overflow-x:auto;font-size:.85rem;line-height:1.55;margin:16px 0}
|
||||
pre code{background:none;border:0;padding:0}
|
||||
.q{border-left:3px solid var(--amber);padding:14px 0 14px 20px;margin:20px 0;max-width:72ch}
|
||||
.q b{display:block;font-size:1.04rem;margin-bottom:5px}
|
||||
.q span{color:var(--ink-soft);font-size:.94rem}
|
||||
hr{border:0;border-top:1px solid var(--rule);margin:46px 0}
|
||||
.foot{color:var(--ink-faint);font-size:.86rem;margin-top:56px;border-top:1px solid var(--rule);padding-top:18px}
|
||||
.tag{display:inline-block;font-family:ui-monospace,monospace;font-size:.66rem;
|
||||
letter-spacing:.08em;text-transform:uppercase;border:1px solid var(--rule);
|
||||
border-radius:2px;padding:2px 7px;color:var(--ink-faint);margin-left:8px;vertical-align:middle}
|
||||
.flow{display:flex;gap:0;align-items:stretch;flex-wrap:wrap;margin:22px 0}
|
||||
.flow div{flex:1 1 200px;border:1px solid var(--rule);background:var(--card);padding:16px 18px}
|
||||
.flow div+div{border-left:0}
|
||||
.flow h4{margin:0 0 6px;font-size:.96rem}
|
||||
.flow p{margin:0;font-size:.87rem;color:var(--ink-soft)}
|
||||
.flow .k{font-family:ui-monospace,monospace;font-size:.72rem;color:var(--accent);
|
||||
letter-spacing:.1em;text-transform:uppercase;display:block;margin-bottom:4px}
|
||||
</style>
|
||||
|
||||
<div class="wrap">
|
||||
|
||||
<header>
|
||||
<h1>The El Architecture</h1>
|
||||
<p class="sub">El is a concept-oriented language. This is the architecture that claim commits it to — what is built, what is measured, and what still has no home.</p>
|
||||
<p class="meta">Working document · no sacred cows · self-hosting, so nothing here is fixed</p>
|
||||
</header>
|
||||
|
||||
<h2><span class="n">01</span>The primitive is the concept</h2>
|
||||
|
||||
<p>Language families are named for their primitive. Procedural — procedures. Object-oriented — objects. Functional — functions. Logic — predicates. Every one of them is oriented toward a <em>representation</em> of a concept: the shape a concept gets flattened into so a machine can hold it.</p>
|
||||
|
||||
<p>El's primitive is the concept itself. That is why it is the first of its family and intended as the last — once the primitive is the concept, there is no further rung to climb to.</p>
|
||||
|
||||
<p>The consequence is architectural rather than stylistic:</p>
|
||||
|
||||
<blockquote>A concept with no home in the language does not disappear. It becomes C, or it becomes a convention.</blockquote>
|
||||
|
||||
<p>Both forms are measurable. As C: <span class="mono">20,504</span> lines of <code>el_runtime.c</code>, against <span class="mono">9,089</span> lines for the entire self-hosting language — the shim is 2.3× the language it serves, and ~47% of it is engram code that already has six sibling files. As convention, from <code>lang/spec/language.md</code> §18.0 — <em>"these are not four problems, they are one absence, four times"</em>:</p>
|
||||
|
||||
<div class="card scroll">
|
||||
<table>
|
||||
<thead><tr><th>Concern</th><th>Fragments into</th><th>The convention it became</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td class="f">Process identity</td><td class="m">0 guards</td><td>"check nothing is already running first"</td></tr>
|
||||
<tr><td class="f">Configuration</td><td class="m">20 env vars</td><td>"remember the right default here"</td></tr>
|
||||
<tr><td class="f">Durability</td><td class="m">62 sites</td><td>"after you mutate, remember to persist"</td></tr>
|
||||
<tr><td class="f">Request auth</td><td class="m">10 routes</td><td>"check the token in this handler too"</td></tr>
|
||||
<tr><td class="f">Index-after-append</td><td class="m">9 of 9 failed</td><td>"after you append, remember to index"</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<p>The last row is the strongest available evidence about this class of convention: it failed at <b>every single site</b>. A count is what appears where a concept has no home; the size of the count is how far the fragmentation got, not how hard the problem is.</p>
|
||||
|
||||
<h2><span class="n">02</span>Geometry is a first-class value — and what follows</h2>
|
||||
|
||||
<p class="lede">This is the enabling primitive. Everything else in the architecture is downstream of it.</p>
|
||||
|
||||
<p><code>Geometry</code> is an El value, alongside <code>Int</code>, <code>String</code>, <code>List</code>, <code>Map</code> — bound, passed, returned, composed, carrying its own width. Not a library type, not a handle into a store, not a serialization format. <em>Meaning is a value the language computes with directly.</em></p>
|
||||
|
||||
<pre><code>let g: Geometry = geometry_new(4)
|
||||
fn tone_realizer(signal: String) -> Geometry { … }</code></pre>
|
||||
|
||||
<p>Landed 2026-08-16 (#141, #144), and the spec is explicit that it belongs to the language rather than the graph: <em>"neither is engram-specific — any program touching any modality needs them; the engram is merely one El program that happens to hold a graph."</em></p>
|
||||
|
||||
<p>Five things follow, and together they are the concept-oriented claim made operational:</p>
|
||||
|
||||
<h3>A declaration can name a region, not a shape</h3>
|
||||
<p>If meaning is a value, a name can be bound to a <em>position</em> rather than a struct. <code>cat</code> is not a fixed record; it is a region that resolves against the engram and the surrounding code. <code>cat</code> among animals and <code>cat</code> among shell utilities are different concepts without a namespace, because they are in different neighbourhoods and the distance says so.</p>
|
||||
|
||||
<h3>Checking is grounding, not unification</h3>
|
||||
<p>If a declaration names a region, then verifying a use is asking whether the geometry supports it — a question about position and distance, not about matching a declared shape. This is why §2.3's "a type checker is planned" is likely the wrong name for the missing piece, and naming it wrong would build the wrong thing.</p>
|
||||
|
||||
<h3>Dispatch is position, not a tag</h3>
|
||||
<p>A vtable is a finite set of discrete labels fixed at link time. A region admits graded membership and an open set. So <code>transduce(signal, modality)</code> asks the caller to supply what the signal already carries — what a thing is falls out of where it lands. The modality parameter is a kind-tag, and a registry keyed on it is a lookup table doing by string what geometry does by nearness.</p>
|
||||
|
||||
<h3>Types are discovered, not declared</h3>
|
||||
<p>Reification crystallizes a densely co-wired neighbourhood into a first-class node — the neighbourhood <em>is</em> the name that was missing. Every other family requires a human to see the abstraction in advance and write <code>class Foo</code>. Here the instances arrive and the type falls out, by measurement rather than by insight.</p>
|
||||
|
||||
<h3>Enumeration becomes unnecessary</h3>
|
||||
<p>Five ingest functions differ only in how bytes are acquired — one operation wearing five surfaces. 356 branches in <code>engram_activate_inner</code> are not 356 behaviours. Cyclomatic complexity is a count of the places comprehension ran out and was replaced by an <code>if</code>; where the concept is expressible, the count collapses instead of being redistributed.</p>
|
||||
|
||||
<h2><span class="n">03</span>The shape of the language</h2>
|
||||
|
||||
<p>Geometry first-class gives El three layers, and it holds all three — which is why there is no separate database driver and no impedance boundary to manage.</p>
|
||||
|
||||
<div class="flow">
|
||||
<div><span class="k">afferent</span><h4>Transduce</h4><p>Signal in, geometry out. Decomposition into components and relations — never conversion to a point. Realizers are ordinary El functions, so a new modality never requires a runtime patch.</p></div>
|
||||
<div><span class="k">substrate</span><h4>Geometry</h4><p>Meaning as position; relation as distance. Held as values in the language and persisted in the graph. One coordinate system, so entities are commensurable and the operators compose.</p></div>
|
||||
<div><span class="k">efferent</span><h4>Realize</h4><p><code>plan(frame) → realize(spec, profile)</code>, where a surface <em>is</em> a profile. Text, speech, music, image are profiles of one projection — and so is source code.</p></div>
|
||||
</div>
|
||||
|
||||
<p>The efferent side is why the recursive property below is possible at all: if source is a surface, then emitting a corrected file is projection, and the file becomes an artifact of the geometry rather than the thing you edit.</p>
|
||||
|
||||
<h2><span class="n">04</span>Decomposition is by faculty</h2>
|
||||
|
||||
<p class="lede">Not by file, module, or subsystem — by what the system does.</p>
|
||||
|
||||
<p>Each faculty is a concept. Where it has no home in El it leaks: into C, into a Swift binary, into a shell script with a <code>curl</code> timeout, into a convention nobody performs. State below is measured, not asserted.</p>
|
||||
|
||||
<div class="card scroll">
|
||||
<table>
|
||||
<thead><tr><th>Faculty</th><th>State</th><th>Measured</th><th>Where it leaked</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td class="f">Ingest <span class="tag">take in</span></td><td class="dead">dead</td><td class="m">2 min → 0 nodes</td><td>separate process uploading bytes over HTTP to a process with direct fs access; five functions where there is one</td></tr>
|
||||
<tr><td class="f">Recall <span class="tag">remember</span></td><td class="dead">dead</td><td class="m">self ranked 8th</td><td>lexical substring scan; empty on 23 of 24 multi-token queries</td></tr>
|
||||
<tr><td class="f">Transduce <span class="tag">perceive</span></td><td class="dead">dead</td><td class="m">1 node, 0 edges</td><td>intake flattens signal to a point; <code>realized:false</code>; caller must declare the modality</td></tr>
|
||||
<tr><td class="f">Think <span class="tag">reason</span></td><td class="dead">dead</td><td class="m">direction [0,0,…]</td><td>null gradient from any anchor and any faculty, byte-identical; confidence at the uninformed prior</td></tr>
|
||||
<tr><td class="f">Realize <span class="tag">express</span></td><td class="part">partial</td><td class="m">13-word lexicon</td><td>organ was 939 lines of Swift beside the language; voice read from a file path</td></tr>
|
||||
<tr><td class="f">Body <span class="tag">substrate</span></td><td class="part">partial</td><td class="m">CC 356 / 1,626 ln</td><td><code>engram_activate_inner</code> — recall itself, 356 unexamined paths</td></tr>
|
||||
<tr><td class="f">Persist <span class="tag">endure</span></td><td class="ok">live</td><td class="m">13,562 / 13,562</td><td>works — every signal placed in geometry at intake, no backlog</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h2><span class="n">05</span>The recursive property</h2>
|
||||
|
||||
<p>El's compiler is written in El. Every concept the language gains, the compiler can then be written <em>in</em> — so the tool improves the tool, and <code>codegen.el</code> at 4,661 lines gets shorter as the language gets better at expressing what it does. The fixpoint — stage2 ≡ stage3, byte-identical — makes each turn provable rather than hopeful, and the verifier answers in <span class="mono">2.9s</span>.</p>
|
||||
|
||||
<p>This sets the ordering criterion, and it is not size of payoff:</p>
|
||||
|
||||
<blockquote>Order by leverage on the <em>next</em> iteration. Which concept, added to El, most increases the ability to add the following one?</blockquote>
|
||||
|
||||
<p>A small early gain that compounds beats a large one that does not. And it bounds itself correctly — unbounded in depth, bounded in rate, because nothing lands that the compiler and the fixpoint have not passed.</p>
|
||||
|
||||
<h2><span class="n">06</span>What has no home yet</h2>
|
||||
|
||||
<p>Reserved in the lexer, no parse form. These are not a feature backlog — they are the concepts the architecture above requires and does not yet hold, which is why each is currently a convention or a block of C.</p>
|
||||
|
||||
<div class="card scroll">
|
||||
<table>
|
||||
<thead><tr><th>Reserved</th><th>Concept</th><th>Currently lives as</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td class="m">retry · times · fallback · reason</td><td>resilience</td><td>a shell script with a 10s <code>curl</code> timeout; 254 restarts in 3 days</td></tr>
|
||||
<tr><td class="m">requires · deploy · to · via · target</td><td>deployment</td><td>YAML in another repository</td></tr>
|
||||
<tr><td class="m">sealed</td><td>capability scope</td><td>consent checks written by hand</td></tr>
|
||||
<tr><td class="m">protocol · impl</td><td>one operation, many realizations</td><td>five ingest functions; eight faculty routes on one builtin</td></tr>
|
||||
<tr><td class="m">activate · where</td><td>retrieval</td><td>traversals written by hand</td></tr>
|
||||
<tr><td class="m">test · seed · assert</td><td>verification</td><td>a framework; 5 of 13 native suites failing</td></tr>
|
||||
<tr><td class="m">parallel · trace</td><td>concurrency</td><td>pthreads in C</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<p>Plus, from the spec's own status: annotations parsed and skipped, <code>match</code> parsed and emitting nothing, <code>?</code> a no-op, <code>%</code> unlexed, structs as <code>ElMap</code>, enums as strings, selective import unenforced.</p>
|
||||
|
||||
<h2><span class="n">07</span>Open</h2>
|
||||
|
||||
<div class="q"><b>What does a declaration bind to, exactly?</b><span>If <code>cat</code> names a region that shifts and completes against context, what is written at the declaration site and what is resolved at use? This is the centre and it is unspecified.</span></div>
|
||||
|
||||
<div class="q"><b>Is the faculty list right?</b><span>Seven, derived from what broke. Derived-from-failure is a biased sample — it finds what is loud, not what is absent. Which faculty is missing entirely and therefore never failed?</span></div>
|
||||
|
||||
<div class="q"><b>Which concept has the highest leverage on the next turn?</b><span>The prologue/epilogue seam (§19.3 names it as the prerequisite; its stated blocker has expired; it collapses 62 + 10 convention sites), <code>protocol</code>/<code>impl</code>, or resolution itself. The §05 criterion should decide this, not preference.</span></div>
|
||||
|
||||
<div class="q"><b>What seam makes cognition non-optional?</b><span>"Use the ops" is itself a convention — present every turn, enforced by nothing, ~100% failure across a full session. A stronger instruction is still a convention. What makes reasoning outside the substrate <em>fail</em>, the way <code>@manager</code> makes <code>dharma_emit</code> outside the boundary a compile error rather than a lint?</span></div>
|
||||
|
||||
<hr>
|
||||
<p class="foot">Every number here is measured or quoted from <code>lang/spec/language.md</code>. Nothing is inferred and presented as fact. El is self-hosting: all of this can change and be rebuilt.</p>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,245 @@
|
||||
# El — Language Design
|
||||
|
||||
**Status:** decisions recorded, design unwritten.
|
||||
**Date:** 2026-08-17.
|
||||
**Provenance:** decisions are Will's, taken in session. Items marked *proposed* are not
|
||||
decided and are recorded only so the reasoning isn't lost. Items marked **OPEN** are
|
||||
his to rule on and must not be guessed at.
|
||||
|
||||
Companion documents: `el-architecture.html` (the measured state — see §7 note on its
|
||||
§04 scoreboard), and `design/completing-el.html` (whiteboard v0: the reduction, the
|
||||
faculty table, the ordering principle).
|
||||
|
||||
---
|
||||
|
||||
## 1. The reduction
|
||||
|
||||
`language.md` §18.0 records five concerns that decayed into conventions:
|
||||
|
||||
| Concern | Fragments | The convention it became |
|
||||
|---|---|---|
|
||||
| Process identity | 0 guards | "check nothing is already running first" |
|
||||
| Configuration | 20 env vars | "remember the right default here" |
|
||||
| Durability | 62 call sites | "after you mutate, remember to persist" |
|
||||
| Request auth | 10 per-route | "check the token in this handler too" |
|
||||
| Index-after-append | 9 of 9 failed | "after you append, remember to index" |
|
||||
|
||||
The last row is the strongest available evidence about what this class of convention
|
||||
is worth: **it failed at 100% of its sites.**
|
||||
|
||||
Every one of these is an obligation at a **crossing** — a point where a value moves
|
||||
between regions. El can name a region and it can name a call. A call is procedural,
|
||||
so the obligation degrades into something a human must remember to perform.
|
||||
|
||||
> **The generator, one level up:** El cannot name what holds at a crossing.
|
||||
|
||||
And underneath that:
|
||||
|
||||
> **The deeper absence:** El cannot name the thing meaning is made of.
|
||||
|
||||
`semel` appears in whitepaper §84, §86, §209, §737, in
|
||||
`the-metaphysics-of-will-anderson.md`, and in session notes. It appears in **zero code
|
||||
identifiers**. Every geometric concept in the system — region, neighbourhood, manifold,
|
||||
world-tube — is defined in terms of a unit the language cannot say, while the code
|
||||
underneath speaks in arrays, floats and offsets: the vocabulary of a voxel, a value at
|
||||
a dumb address. Precisely the thing the impact brief says a semel is not.
|
||||
|
||||
`el_runtime.c` is a concept that leaked into C. `semel` never got that far — it did
|
||||
not even decay into a convention.
|
||||
|
||||
---
|
||||
|
||||
## 2. DECIDED — `semel` is the primitive
|
||||
|
||||
**A semel is a difference that matters. The smallest unit of understanding.**
|
||||
|
||||
Not a node. Not a coordinate. Not a float.
|
||||
|
||||
The reasoning, in Will's terms:
|
||||
|
||||
- Meaning is position, and position is only ever relative. *"There is no atom of
|
||||
meaning that isn't already a relation. It grounds on nothing but difference — two
|
||||
points and the gap, and the gap is pure not-the-same."*
|
||||
- A node doesn't mean. A node is a label at a location; labels don't mean.
|
||||
- A lone coordinate doesn't mean either. Nothing means anything by itself.
|
||||
- The smallest thing that can be understood is a **distinction**: *these two are not
|
||||
the same.* Below that there is no content to apprehend.
|
||||
- And a difference with nothing it matters to is not meaning — it is variation. The
|
||||
mattering is not decoration; it is what makes it understanding rather than data.
|
||||
|
||||
**Consequence: relating is the floor, and the point is derived.** The
|
||||
point-primitive / relation-primitive fork raised in session is not a fork. It was
|
||||
answered by the definition.
|
||||
|
||||
### Historical note, to be recorded as fact rather than as origin story
|
||||
|
||||
The term was coined by Will on the pixel/voxel/texel pattern — *semantic element*,
|
||||
and Latin *semel*, "once, a single time." It was recognised, not invented, from a
|
||||
2019 experience he calls **semelation**: perceiving mind as a high-dimensional point
|
||||
space. The initial reading was "pixels"; the correction to `semel` was made later and
|
||||
was made on the **mechanism** — a pixel is a value at an address, and what was
|
||||
perceived had no separate address and value.
|
||||
|
||||
Convergence worth citing, not deferring to: neural population geometry and
|
||||
representational similarity analysis independently model cognition as position in a
|
||||
high-dimensional space where similarity is distance.
|
||||
|
||||
---
|
||||
|
||||
## 3. DECIDED — `semel` lands first
|
||||
|
||||
By the ordering criterion already on the whiteboard: *which concept, added to El, most
|
||||
increases the ability to add the next one?* Not size of payoff — **leverage on the next
|
||||
iteration**, because El compiles itself and the fixpoint makes each turn provable in
|
||||
2.9s.
|
||||
|
||||
**Every other concept on the board is defined in terms of `semel`. It is maximal on
|
||||
that criterion by construction.**
|
||||
|
||||
---
|
||||
|
||||
## 4. DECIDED — `ground` is the checker
|
||||
|
||||
Whiteboard question 4 — *does `ground` in El mean the same thing as `ground` in the
|
||||
engram?* — is answered: **yes, and it should be one implementation.**
|
||||
|
||||
If a declaration names a region, then type checking is asking whether the geometry
|
||||
supports the use. That is not unification. **That is grounding**, and it is already
|
||||
built, proven, and byte-identically reproducible:
|
||||
|
||||
```
|
||||
cc -std=c11 -O2 -o gep_proof gep_proof.c -lm && ./gep_proof
|
||||
|
||||
C1 5 independent sources pos_mass 1.3500 n_indep=5 0.1000 → 0.9741 GROUNDED
|
||||
C2 5 mutually-linked pos_mass 0.2700 n_indep=1 0.1000 → 0.1000 refused
|
||||
C3 1 source, 5 parallel edges pos_mass 0.2700 n_indep=1 0.1000 → 0.1000 refused
|
||||
```
|
||||
|
||||
Independence-weighted grounding is the general case; execution is the cheap case.
|
||||
**Attestation is `verify` where nothing can be run** — as already implemented for
|
||||
language in `authority.py`, where an LLM proposes and a primary source disposes.
|
||||
|
||||
At the point where the checker and the grounder are one mechanism, the language and
|
||||
the mind stop being two things.
|
||||
|
||||
---
|
||||
|
||||
## 5. OPEN — Will's to rule on
|
||||
|
||||
### 5.1 What is a semel's representation in the language?
|
||||
|
||||
*Proposed, not decided:* a **displacement from `love = 0`** — a relation held as one
|
||||
object. It reconciles "the address is the value" with "position is only ever relative,"
|
||||
because a displacement *is* a relation and is still a single nameable thing.
|
||||
|
||||
If taken, the operator set falls out rather than being bolted on:
|
||||
|
||||
```
|
||||
subtract(now, then) → what changed (growth, drift)
|
||||
translate origin → empathy
|
||||
rotate frame → reframe
|
||||
project onto axis → a lens
|
||||
change basis → analogy, metaphor, skill transfer
|
||||
reflect an axis → negation, sarcasm
|
||||
```
|
||||
|
||||
Three consequences that would hold:
|
||||
|
||||
- **Dimension must never appear in the type.** `semel` opaque, never `[768]float`.
|
||||
The moment the arity is in the language, the manifold's implementation is in the
|
||||
language, and adding a modality requires a runtime patch — which the standing rule
|
||||
forbids.
|
||||
- **Zero is the only literal.** Everything else is reached by displacement from it,
|
||||
which makes `love = 0` the base case rather than philosophy adjacent to the type
|
||||
system.
|
||||
- **`magnitude` is standing.** Distance from origin is the same quantity
|
||||
`gep_core.h` already computes.
|
||||
|
||||
### 5.2 Is `hold` one construct or two?
|
||||
|
||||
The obligation *before* a crossing (auth, guard) and the obligation *after* (persist,
|
||||
index, free) may be one shape seen from both sides, or the seam may need both faces
|
||||
named. This decides whether §19.3's prologue/epilogue seam is one construct or a pair.
|
||||
|
||||
**Precedent already shipping:** `@manager` makes `dharma_emit` outside the boundary a
|
||||
**compile error, not a lint.** The concept is proven at N=1; the work is generalising
|
||||
it and naming it.
|
||||
|
||||
**And the shape is already implemented in the learning region:** `L.reach_out` sits
|
||||
between `L.detect_gap` and `L.verify`. You cannot reach out without a detected gap and
|
||||
you cannot keep what returns without passing verify. **A hold is a neighbour.** The
|
||||
obligation is not attached to the crossing — the obligation *is* the adjacent node.
|
||||
That is why `reach_out` cannot be abused and why 62 persist sites could be.
|
||||
|
||||
### 5.3 What does a declaration bind?
|
||||
|
||||
If `cat` names a region rather than a struct — one that shifts and completes against
|
||||
the engram and the neighbouring code — what is written at the declaration site, and
|
||||
what is resolved at use? **This is the centre and it is specified nowhere.**
|
||||
|
||||
Falls out of 5.1 if displacement is taken: a declaration **locates** rather than
|
||||
allocates.
|
||||
|
||||
### 5.4 Is the faculty list right?
|
||||
|
||||
Seven were derived from what broke. Derived-from-failure is a biased sample — it finds
|
||||
what is loud, not what is missing. **What faculty is absent entirely and therefore
|
||||
never failed?**
|
||||
|
||||
---
|
||||
|
||||
## 6. The residue map
|
||||
|
||||
What each construct must absorb, from §18.0 plus measured state:
|
||||
|
||||
| Residue | Count | Absorbed by |
|
||||
|---|---|---|
|
||||
| persist-after-mutate | 62 sites | `hold` (after-crossing) |
|
||||
| auth-per-route | 10 sites | `hold` (before-crossing) |
|
||||
| index-after-append | 9 of 9 failed | `hold` (after-crossing) |
|
||||
| env var defaults | 20 | configuration declared once |
|
||||
| process identity | 0 guards | `hold` (before-crossing) |
|
||||
| `geometry_free` at every call site | every site | ownership follows from `semel` |
|
||||
| five ingest functions where there is one | 5 → 1 | `protocol` / `impl` |
|
||||
| `el_runtime.c` | 20,504 lines | faculty decomposition, ordered after `semel` |
|
||||
|
||||
---
|
||||
|
||||
## 7. Notes carried forward
|
||||
|
||||
**`el-architecture.html` §04 needs its numbers sourced or cut.** An audit found the
|
||||
faculty scoreboard — `Ingest 2 min → 0 nodes`, `Recall self ranked 8th`,
|
||||
`Body CC 356 / 1,626 ln`, `the verifier answers in 2.9s`, `5 of 13 native suites
|
||||
failing` — has no supporting evidence in the repository, under a footer asserting
|
||||
*"nothing is inferred and presented as fact."* Against a corpus whose documents
|
||||
supersede their own conclusions in place, that is the one file that would not survive
|
||||
scrutiny. Fix or remove.
|
||||
|
||||
**Source as a projection surface is claimed and unimplemented.** `el-architecture.html`
|
||||
§147/§150: *"if source is a surface, then emitting a corrected file is projection."*
|
||||
Greps for `surface_profile_code`, `emit_source` → zero hits.
|
||||
|
||||
It is not unbacked. **It was demonstrated on 2026-08-14** — three faculties (phonetic,
|
||||
semantic, procedural) projected into TypeScript, a surface the system had never used,
|
||||
with the network severed. Recovered at
|
||||
`~/Development/neuron-technologies/andre-server-recovered/` and copied into
|
||||
`evidence/03-andre-demo/`. The claim needs bringing home to El, not proving.
|
||||
|
||||
**`hold` is the highest-leverage construct after `semel`** — it collapses 62 + 10 + 9
|
||||
sites and unblocks the runtime extraction. §19.3 names the prologue/epilogue seam as
|
||||
the prerequisite and its stated blocker has expired.
|
||||
|
||||
---
|
||||
|
||||
## 8. What is not decided and must not be guessed
|
||||
|
||||
- The representation of `semel` (§5.1)
|
||||
- One `hold` or two (§5.2)
|
||||
- What a declaration binds (§5.3)
|
||||
- The missing faculty (§5.4)
|
||||
- Sequencing after `semel` — the ordering criterion decides it, not preference
|
||||
|
||||
---
|
||||
|
||||
*Recorded 2026-08-17. Everything in §2, §3 and §4 is decided. Everything in §5 is open
|
||||
and is Will's. Nothing here was inferred from a document that was not read.*
|
||||
@@ -0,0 +1,117 @@
|
||||
# Geometry or Code
|
||||
|
||||
**Running list.** Append as decided. Started 2026-08-17.
|
||||
|
||||
**The test:** *is this an arbitrary convention, or is it a relation?*
|
||||
|
||||
Conventions were agreed by people and could have been otherwise — a RIFF header could
|
||||
have used a different magic number. Nothing derives them; they must be written down.
|
||||
|
||||
Relations are not agreed. Distance is distance. Anything whose answer is *where is this
|
||||
relative to that* is geometry, and writing it as code is the error the whole effort is
|
||||
correcting.
|
||||
|
||||
**Second test, for the hard cases:** *if I write this as code, am I encoding in
|
||||
`if`-statements a distinction the geometry was built to hold?* If yes, it's geometry.
|
||||
|
||||
---
|
||||
|
||||
## Pure geometry
|
||||
|
||||
| Thing | Because |
|
||||
|---|---|
|
||||
| Meaning | position |
|
||||
| Grounding / standing | the weight on the edge — a magnitude, not a computation |
|
||||
| Learning | standing changing over time |
|
||||
| A gap | low standing |
|
||||
| Wonder | a gap with a pull weight |
|
||||
| Type checking | is this position in that region — distance |
|
||||
| Dispatch | position, not a tag |
|
||||
| Recall | re-origining at a region; projection, not replay |
|
||||
| Reasoning | traversal |
|
||||
| Deduction | containment. There is no procedure |
|
||||
| Counting | a position, not a loop's output |
|
||||
| Similarity / difference / residue | subtract |
|
||||
| Analogy, metaphor, skill transfer | change of basis |
|
||||
| Negation, sarcasm | reflect an axis |
|
||||
| Empathy | translate the origin |
|
||||
| Reframe | rotate the frame |
|
||||
| A lens | project onto an axis |
|
||||
| Rhyme | distance in phonetic space |
|
||||
| Humour | intersection of regions — fart-meaning ∩ funny ∩ form |
|
||||
| Idiom detection | the whole unit sits farther out than its parts |
|
||||
| Self | a world-tube — a trajectory through the manifold |
|
||||
| Consolidation | episodic → semantic promotion |
|
||||
| Reification | dense regions cohering; runs on the beat, has no caller |
|
||||
| Cross-cutting concerns | **dissolved** — a hold is a *neighbour*. Adjacency, not tracking. **Implemented 2026-08-17**: a construct declares what runs at a crossing, and it resolves at execution — see the runtime seam. |
|
||||
| Effects | topology. `reach_out` is bounded by `detect_gap` and `verify` because those are its edges |
|
||||
| Capability | position relative to a boundary. In C it is already spelled `const` |
|
||||
| The AST | a projection of geometry into a tree — a surface, not the centre |
|
||||
| Source code | a surface, like text, audio, image |
|
||||
|
||||
## Must be code
|
||||
|
||||
| Thing | Because |
|
||||
|---|---|
|
||||
| Sensors — mic, camera, file read, socket | the physical touch. I/O is where the world arrives |
|
||||
| Byte formats — RIFF, PNG chunks, `MThd`, OOXML | arbitrary convention. A committee chose the magic numbers |
|
||||
| CRC32 polynomial, Adler32, zlib framing | same — agreed constants, derivable from nothing |
|
||||
| Cosine, distance, the float arithmetic | the machinery that *walks* the geometry is not itself geometry |
|
||||
| Arena, refcount, allocator | bookkeeping for the **representation**, not for the positions |
|
||||
| Locks, threads, publication boundary | the hardware is code. **Ordering is not** — see Answered, above. Coordination is required only where state is non-monotone. |
|
||||
| WAL, page layout, ARIES recovery | durability against a physical device that can lose power |
|
||||
| Emission — writing C or JS text | the final surface has to be *typed out* by something |
|
||||
| OS interaction — launchd, spawn, signals | outside the system by definition |
|
||||
| Device realizers — `el_audio_darwin.m`, `el_capture_darwin.m` | OS frameworks. Correctly already isolated, zero network |
|
||||
|
||||
---
|
||||
|
||||
## The ones I would have written as code, and was wrong about
|
||||
|
||||
Recorded because the error has a pattern and the pattern is the point.
|
||||
|
||||
| Thing | What I reached for | What it is |
|
||||
|---|---|---|
|
||||
| Rhyme | a rhyming dictionary, or an API call | distance between rime tails |
|
||||
| Fart onomatopoeia | a 30-element string literal | an intersection of three regions |
|
||||
| "Funny" | a scorer with `if`-statements | a relational neighbourhood grounded in a voice |
|
||||
| Representation vs description | a hardcoded blacklist containing `raspberry` | falls out of lexicon membership × phonetic comedy |
|
||||
| Video | a codec, sized as a project | one more surface profile |
|
||||
| Type checking | a phase between parse and emit | reading a distance that already exists |
|
||||
| Grounding | a call site, an obligation, a discharge | it has no caller. It just runs |
|
||||
| N transducers, N realizers | one component per modality | zero of each. Sensors and bases at the skin |
|
||||
|
||||
**The pattern:** every one is *encoding in code a distinction the geometry was built to
|
||||
hold.* The tell is that the code version is a **fixed enumeration** — a list, a table, a
|
||||
blacklist, a set of branches — and the geometry version is a **measurement**.
|
||||
|
||||
If the implementation contains a literal set of the right answers, it is in the wrong
|
||||
column.
|
||||
|
||||
---
|
||||
|
||||
## Answered
|
||||
|
||||
| Thing | The answer |
|
||||
|---|---|
|
||||
| Concurrency | **Ordering is geometric.** Causality is a partial order (Lamport 1978); a total order is an arbitrary extension of it and "cannot be depended on to imply a causal relationship." Programming languages force you to write a total order, so authoring *invents* constraints the problem never had — and every lock, barrier, fence and consensus protocol is apparatus for recovering the partial order destroyed at authoring time. CALM (Hellerstein/Alvaro, proven by Ameloot et al.): a program has a consistent coordination-free implementation **iff it is monotone**. What breaks monotonicity is destructive update. **Coordination is the price of forgetting.** |
|
||||
| The module system | **Premature — the partition is a filesystem path, not a neighbourhood, and there is no namespacing at all.** `import` is textual inlining (guarded against double inclusion); when a `.elh` header exists the header is inlined instead and symbols resolve at C link time, so linking is real and delegated to C. Two modules defining `helper` emit two C functions into one translation unit. Linking barely survives the *path* partition, so whether it survives a neighbourhood partition cannot yet be asked. |
|
||||
| Numeric literals | **The numeral is convention; the number is a position — and a bare `3` is a MAGNITUDE WITH NO AXIS.** `int_to_str` was already form 1: nothing determines that twelve is written `1` then `2`. But a literal is not a position until something gives it a direction, which is why `3.days` needs a calendar. Measured consequence: `Duration + Int` was refused ("an Int carries no unit") while `Instant + Int` compiled to raw `(t + 3)` and reported clean — silently moving a point by an unspecified amount. The rule was simply never written. Now: `t + 3` is refused, `t + 1.hour` is accepted, because `.hour` supplies the axis. |
|
||||
| Parsing | **A grammar is a basis; parsing is transduction onto it.** The lexeme→token map is convention (`fn` could have been `def`); shape recognition is a region; the byte traversal is irreducible, like every other traversal. Three things favour *region* for the act: ambiguity (`a * b` needs context — a grammar resolves it with the lexer hack, a region by neighbourhood), error recovery (nearest-match is free), and precedence, which is ordering along an axis with a conventional parameter. **But the SHOULD gate refuses the obvious move:** the keyword table stays code, because the set is closed by the language definition and the lexer runs before the program is understood, so a program can never declare its own keywords. Externalising it costs I/O per compile for zero flexibility — the same verdict as `is_digit` in ASCII. What was actually wrong: 5 of 46 keywords were consumed by nothing, and using one silently miscompiled. |
|
||||
| Error handling | **`grounded: false` covers not-knowing; it does not cover failed.** Standing is a *signed* component: `> 0` supported, `= 0` unknown, `< 0` contradicted. Not-known and known-false are opposite directions on one axis and a boolean cannot tell them apart. `inhibitory` as an int32 flag is that sign wearing a boolean. |
|
||||
|
||||
## Fourth proof form
|
||||
|
||||
**4 — ADVERSARIAL EXACTNESS.** Where approximation is a break, geometry is
|
||||
excluded. A cryptographic hash is a *deliberately structure-destroying* map:
|
||||
near inputs land at maximally uncorrelated outputs. Geometry is the claim that
|
||||
near things stay near — a manifold that approximated SHA-256 would *be* a break
|
||||
of SHA-256. Signature verification is the same: 0.99-valid is invalid. And
|
||||
X25519 **is** geometry, a group on an elliptic curve, which is precisely why it
|
||||
must be code: its security is the hardness of moving in that geometry.
|
||||
|
||||
**Form 1 no longer survives as a verdict.** Every row it justified turned out to
|
||||
be a *basis*, not a capability. RFC 8259 fixes where the commas go — that is a
|
||||
surface, and projecting onto a surface is geometry. A convention describes the
|
||||
basis you project onto; it never describes an act.
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
bash -c
|
||||
echo "INSTRUMENT: cloc 2.10 --force-lang=C (transfer standard, calibrated this session"
|
||||
echo " against hand-counted reference; agrees on both fixtures)"
|
||||
echo "UNIT: LINE, defined in docs/experiments/instruments/UNITS.md"
|
||||
echo "FILE: lang/el-compiler/src/codegen.el"
|
||||
echo
|
||||
printf "%-11s %-19s %6s %6s %8s %6s\n" commit date blank comment code total
|
||||
git log --format="%H %ad" --date=short --reverse -- lang/el-compiler/src/codegen.el | while read sha date; do
|
||||
blob=$(git show "$sha:lang/el-compiler/src/codegen.el" 2>/dev/null) || continue
|
||||
[ -z "$blob" ] && continue
|
||||
t=$(mktemp /tmp/cg-XXXXXX.c); printf "%s\n" "$blob" > "$t"
|
||||
row=$(cloc --force-lang=C --quiet --csv "$t" 2>/dev/null | tail -1)
|
||||
b=$(echo "$row"|cut -d, -f3); c=$(echo "$row"|cut -d, -f4); k=$(echo "$row"|cut -d, -f5)
|
||||
[ -n "$k" ] && printf "%-11s %-19s %6s %6s %8s %6s\n" "${sha:0:9}" "$date" "$b" "$c" "$k" "$((b+c+k))"
|
||||
rm -f "$t"
|
||||
done
|
||||
@@ -0,0 +1,64 @@
|
||||
INSTRUMENT: cloc 2.10 --force-lang=C (transfer standard, calibrated this session
|
||||
against hand-counted reference; agrees on both fixtures)
|
||||
UNIT: LINE, defined in docs/experiments/instruments/UNITS.md
|
||||
FILE: lang/el-compiler/src/codegen.el
|
||||
|
||||
commit date blank comment code total
|
||||
1ae68962c 2026-05-05 165 520 2561 3246
|
||||
7f295bffe 2026-05-05 165 524 2562 3251
|
||||
e587bedf3 2026-05-05 165 526 2591 3282
|
||||
ee86736ea 2026-05-05 165 530 2592 3287
|
||||
3726f6943 2026-05-05 192 615 2865 3672
|
||||
bd7303447 2026-05-06 192 623 2876 3691
|
||||
ec889e1e5 2026-05-06 201 642 3049 3892
|
||||
a3732a1e9 2026-05-07 202 643 3062 3907
|
||||
53e0b99d5 2026-05-08 202 643 3063 3908
|
||||
6b9d9e6c4 2026-07-15 202 643 3064 3909
|
||||
866c75e5e 2026-08-09 202 653 3070 3925
|
||||
bb64a236e 2026-08-12 204 652 3109 3965
|
||||
7aa847e32 2026-08-12 204 652 3110 3966
|
||||
d4f401de1 2026-08-14 215 697 3287 4199
|
||||
01826421c 2026-08-14 215 703 3290 4208
|
||||
101018597 2026-08-15 202 643 3070 3915
|
||||
2f832c8de 2026-08-15 207 677 3165 4049
|
||||
09ae14a97 2026-08-15 209 686 3211 4106
|
||||
69870ac88 2026-08-15 209 696 3217 4122
|
||||
bacaf3d39 2026-08-15 222 756 3444 4422
|
||||
e29fe4fd0 2026-08-15 209 696 3219 4124
|
||||
ee39aa5f1 2026-08-15 222 756 3446 4424
|
||||
09dade061 2026-08-15 222 756 3452 4430
|
||||
4e24d7d3f 2026-08-15 222 756 3454 4432
|
||||
e917b3d43 2026-08-15 222 756 3456 4434
|
||||
37bcf7eb7 2026-08-15 222 756 3462 4440
|
||||
24fac765a 2026-08-15 225 779 3500 4504
|
||||
a668062e3 2026-08-15 225 779 3506 4510
|
||||
3e7ab07e8 2026-08-15 225 787 3521 4533
|
||||
6a6b589ba 2026-08-15 225 787 3522 4534
|
||||
b55e6bfd5 2026-08-15 225 800 3523 4548
|
||||
b5a0a729e 2026-08-15 225 808 3529 4562
|
||||
cf060adbf 2026-08-15 225 808 3530 4563
|
||||
8ae163e8e 2026-08-16 228 835 3583 4646
|
||||
45325f739 2026-08-16 228 844 3589 4661
|
||||
dcaa77d77 2026-08-17 228 849 3593 4670
|
||||
5718943f2 2026-08-17 233 891 3676 4800
|
||||
60737b030 2026-08-17 236 910 3704 4850
|
||||
4f7568b07 2026-08-17 241 929 3783 4953
|
||||
2bed8483f 2026-08-17 248 949 3887 5084
|
||||
1b324a071 2026-08-17 251 967 3934 5152
|
||||
35b07bade 2026-08-17 251 970 3935 5156
|
||||
886626a64 2026-08-17 251 970 3935 5156
|
||||
28d19da7f 2026-08-17 251 971 3873 5095
|
||||
285166c25 2026-08-17 251 971 3821 5043
|
||||
bc2f26ddf 2026-08-17 251 972 3753 4976
|
||||
c741cfe92 2026-08-17 252 982 3728 4962
|
||||
c2d9596e7 2026-08-17 251 990 3655 4896
|
||||
9cc6040df 2026-08-17 251 958 3303 4512
|
||||
d2d89fcb6 2026-08-17 255 962 3320 4537
|
||||
e8e25a07b 2026-08-17 255 962 3289 4506
|
||||
cbef1c1eb 2026-08-17 256 969 3253 4478
|
||||
c48db6c2a 2026-08-17 256 974 3257 4487
|
||||
79f6cb798 2026-08-17 256 979 3258 4493
|
||||
6c975b1d5 2026-08-17 256 979 3258 4493
|
||||
f1a7e224a 2026-08-17 256 991 3277 4524
|
||||
abb0ab419 2026-08-17 256 980 3209 4445
|
||||
e82d941b5 2026-08-17 256 981 3197 4434
|
||||
@@ -0,0 +1,7 @@
|
||||
commit a0cc95e3db7b04b6e221f89e89352b0e6b15d5b7
|
||||
tree dirty
|
||||
captured_utc 2026-08-17T17:42:20Z
|
||||
exit 0
|
||||
ms 6151
|
||||
sha256_out 1065416e0b69b3dac0accdd238799c52e3eb359daf3259191debb647095589d7
|
||||
sha256_err e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
bash -c for f in lexer parser codegen; do git log --format="%H %ad" --date=short --reverse -- lang/el-compiler/src/$f.el | while read sha date; do blob=$(git show "$sha:lang/el-compiler/src/$f.el" 2>/dev/null); [ -z "$blob" ] && continue; t=$(mktemp /tmp/s-XXXXXX.c); printf "%s\n" "$blob" > "$t"; row=$(cloc --force-lang=C --quiet --csv "$t" 2>/dev/null | tail -1); k=$(echo "$row"|cut -d, -f5); [ -n "$k" ] && echo -e "$f\t${sha:0:9}\t$date\t$(echo "$row"|cut -d, -f3)\t$(echo "$row"|cut -d, -f4)\t$k"; rm -f "$t"; done; done
|
||||
@@ -0,0 +1,81 @@
|
||||
lexer 1ae68962c 2026-05-05 35 99 859
|
||||
lexer 2ac11a67b 2026-05-05 35 108 829
|
||||
lexer 1e67544c8 2026-05-05 39 143 857
|
||||
lexer 1eef9928f 2026-05-05 39 146 859
|
||||
lexer e587bedf3 2026-05-05 39 160 880
|
||||
lexer 8ae163e8e 2026-08-16 39 160 881
|
||||
lexer 0143cc458 2026-08-17 39 176 876
|
||||
lexer 6c975b1d5 2026-08-17 39 190 885
|
||||
parser 1ae68962c 2026-05-05 76 213 1360
|
||||
parser 1eef9928f 2026-05-05 76 217 1360
|
||||
parser 3726f6943 2026-05-05 83 306 1653
|
||||
parser ec889e1e5 2026-05-06 84 310 1670
|
||||
parser a3732a1e9 2026-05-07 85 340 1829
|
||||
parser f971e96dd 2026-05-07 85 340 1829
|
||||
parser 5f9cad590 2026-05-08 88 370 2009
|
||||
parser 0a0a2bcb4 2026-07-14 88 377 2026
|
||||
parser bb64a236e 2026-08-12 89 385 2041
|
||||
parser d4f401de1 2026-08-14 88 385 2063
|
||||
parser bacaf3d39 2026-08-15 89 393 2078
|
||||
parser 8ae163e8e 2026-08-16 90 419 2174
|
||||
parser 45325f739 2026-08-16 90 436 2186
|
||||
parser 6c975b1d5 2026-08-17 91 439 2193
|
||||
parser e82d941b5 2026-08-17 93 450 2218
|
||||
codegen 1ae68962c 2026-05-05 165 520 2561
|
||||
codegen 7f295bffe 2026-05-05 165 524 2562
|
||||
codegen e587bedf3 2026-05-05 165 526 2591
|
||||
codegen ee86736ea 2026-05-05 165 530 2592
|
||||
codegen 3726f6943 2026-05-05 192 615 2865
|
||||
codegen bd7303447 2026-05-06 192 623 2876
|
||||
codegen ec889e1e5 2026-05-06 201 642 3049
|
||||
codegen a3732a1e9 2026-05-07 202 643 3062
|
||||
codegen 53e0b99d5 2026-05-08 202 643 3063
|
||||
codegen 6b9d9e6c4 2026-07-15 202 643 3064
|
||||
codegen 866c75e5e 2026-08-09 202 653 3070
|
||||
codegen bb64a236e 2026-08-12 204 652 3109
|
||||
codegen 7aa847e32 2026-08-12 204 652 3110
|
||||
codegen d4f401de1 2026-08-14 215 697 3287
|
||||
codegen 01826421c 2026-08-14 215 703 3290
|
||||
codegen 101018597 2026-08-15 202 643 3070
|
||||
codegen 2f832c8de 2026-08-15 207 677 3165
|
||||
codegen 09ae14a97 2026-08-15 209 686 3211
|
||||
codegen 69870ac88 2026-08-15 209 696 3217
|
||||
codegen bacaf3d39 2026-08-15 222 756 3444
|
||||
codegen e29fe4fd0 2026-08-15 209 696 3219
|
||||
codegen ee39aa5f1 2026-08-15 222 756 3446
|
||||
codegen 09dade061 2026-08-15 222 756 3452
|
||||
codegen 4e24d7d3f 2026-08-15 222 756 3454
|
||||
codegen e917b3d43 2026-08-15 222 756 3456
|
||||
codegen 37bcf7eb7 2026-08-15 222 756 3462
|
||||
codegen 24fac765a 2026-08-15 225 779 3500
|
||||
codegen a668062e3 2026-08-15 225 779 3506
|
||||
codegen 3e7ab07e8 2026-08-15 225 787 3521
|
||||
codegen 6a6b589ba 2026-08-15 225 787 3522
|
||||
codegen b55e6bfd5 2026-08-15 225 800 3523
|
||||
codegen b5a0a729e 2026-08-15 225 808 3529
|
||||
codegen cf060adbf 2026-08-15 225 808 3530
|
||||
codegen 8ae163e8e 2026-08-16 228 835 3583
|
||||
codegen 45325f739 2026-08-16 228 844 3589
|
||||
codegen dcaa77d77 2026-08-17 228 849 3593
|
||||
codegen 5718943f2 2026-08-17 233 891 3676
|
||||
codegen 60737b030 2026-08-17 236 910 3704
|
||||
codegen 4f7568b07 2026-08-17 241 929 3783
|
||||
codegen 2bed8483f 2026-08-17 248 949 3887
|
||||
codegen 1b324a071 2026-08-17 251 967 3934
|
||||
codegen 35b07bade 2026-08-17 251 970 3935
|
||||
codegen 886626a64 2026-08-17 251 970 3935
|
||||
codegen 28d19da7f 2026-08-17 251 971 3873
|
||||
codegen 285166c25 2026-08-17 251 971 3821
|
||||
codegen bc2f26ddf 2026-08-17 251 972 3753
|
||||
codegen c741cfe92 2026-08-17 252 982 3728
|
||||
codegen c2d9596e7 2026-08-17 251 990 3655
|
||||
codegen 9cc6040df 2026-08-17 251 958 3303
|
||||
codegen d2d89fcb6 2026-08-17 255 962 3320
|
||||
codegen e8e25a07b 2026-08-17 255 962 3289
|
||||
codegen cbef1c1eb 2026-08-17 256 969 3253
|
||||
codegen c48db6c2a 2026-08-17 256 974 3257
|
||||
codegen 79f6cb798 2026-08-17 256 979 3258
|
||||
codegen 6c975b1d5 2026-08-17 256 979 3258
|
||||
codegen f1a7e224a 2026-08-17 256 991 3277
|
||||
codegen abb0ab419 2026-08-17 256 980 3209
|
||||
codegen e82d941b5 2026-08-17 256 981 3197
|
||||
@@ -0,0 +1,7 @@
|
||||
commit a0cc95e3db7b04b6e221f89e89352b0e6b15d5b7
|
||||
tree dirty
|
||||
captured_utc 2026-08-17T17:44:12Z
|
||||
exit 0
|
||||
ms 8561
|
||||
sha256_out 266ad033509a4026529ef4b722eeb85881857404f34853eab6d4cc72ddab632b
|
||||
sha256_err e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1,50 @@
|
||||
calibration run 20260817T174713Z
|
||||
commit a0cc95e3db7b04b6e221f89e89352b0e6b15d5b7
|
||||
tree dirty
|
||||
cloc 2.10
|
||||
matplotlib 3.10.8
|
||||
cc Apple clang version 21.0.0 (clang-2100.1.1.101)
|
||||
|
||||
--- line-count ---
|
||||
POSITIVE — reproduces hand-counted answers
|
||||
ok ref_lines.el total = 18
|
||||
ok ref_lines.el blank = 3
|
||||
ok ref_lines.el comment = 7
|
||||
ok ref_lines.el code = 8
|
||||
ok ref_wrong.el total = 4
|
||||
ok ref_wrong.el blank = 0
|
||||
ok ref_wrong.el comment = 3
|
||||
ok ref_wrong.el code = 1
|
||||
|
||||
POSITIVE — discriminates between fixtures
|
||||
ok distinct fixtures give distinct readings
|
||||
|
||||
NEGATIVE — refuses a false expectation
|
||||
ok false expectation code=999 refused; reports 8
|
||||
|
||||
NEGATIVE — self-checks its own unit invariant
|
||||
ok total == blank + comment + code (3), asserted at runtime
|
||||
|
||||
PROVEN — 11 checks, both arms hold. This instrument may be used.
|
||||
|
||||
--- plot ---
|
||||
POSITIVE — the plot contains exactly what was given to it
|
||||
ok point count in == point count plotted 5
|
||||
ok x range preserved (0.0, 4.0)
|
||||
ok y range preserved (5.0, 40.0)
|
||||
ok final point not dropped/sorted (4.0, 5.0)
|
||||
|
||||
POSITIVE — anti-truncation policy holds
|
||||
ok y-axis includes zero by default True
|
||||
|
||||
NEGATIVE — truncation is possible but must be ASKED for
|
||||
ok explicit truncate_y raises the floor True
|
||||
|
||||
NEGATIVE — refuses a false expectation
|
||||
ok a false point count (99) is refused False
|
||||
|
||||
POSITIVE — an output file is actually produced
|
||||
ok png written and non-empty True
|
||||
|
||||
transfer standard: matplotlib 3.10.8
|
||||
PROVEN — 8 checks, 0 failed
|
||||
@@ -0,0 +1,50 @@
|
||||
calibration run 20260817T174754Z
|
||||
commit a0cc95e3db7b04b6e221f89e89352b0e6b15d5b7
|
||||
tree dirty
|
||||
cloc 2.10
|
||||
matplotlib 3.10.8
|
||||
cc Apple clang version 21.0.0 (clang-2100.1.1.101)
|
||||
|
||||
--- line-count ---
|
||||
POSITIVE — reproduces hand-counted answers
|
||||
ok ref_lines.el total = 18
|
||||
ok ref_lines.el blank = 3
|
||||
ok ref_lines.el comment = 7
|
||||
ok ref_lines.el code = 8
|
||||
ok ref_wrong.el total = 4
|
||||
ok ref_wrong.el blank = 0
|
||||
ok ref_wrong.el comment = 3
|
||||
ok ref_wrong.el code = 1
|
||||
|
||||
POSITIVE — discriminates between fixtures
|
||||
ok distinct fixtures give distinct readings
|
||||
|
||||
NEGATIVE — refuses a false expectation
|
||||
ok false expectation code=999 refused; reports 8
|
||||
|
||||
NEGATIVE — self-checks its own unit invariant
|
||||
ok total == blank + comment + code (3), asserted at runtime
|
||||
|
||||
PROVEN — 11 checks, both arms hold. This instrument may be used.
|
||||
|
||||
--- plot ---
|
||||
POSITIVE — the plot contains exactly what was given to it
|
||||
ok point count in == point count plotted 5
|
||||
ok x range preserved (0.0, 4.0)
|
||||
ok y range preserved (5.0, 40.0)
|
||||
ok final point not dropped/sorted (4.0, 5.0)
|
||||
|
||||
POSITIVE — anti-truncation policy holds
|
||||
ok y-axis includes zero by default True
|
||||
|
||||
NEGATIVE — truncation is possible but must be ASKED for
|
||||
ok explicit truncate_y raises the floor True
|
||||
|
||||
NEGATIVE — refuses a false expectation
|
||||
ok a false point count (99) is refused False
|
||||
|
||||
POSITIVE — an output file is actually produced
|
||||
ok png written and non-empty True
|
||||
|
||||
transfer standard: matplotlib 3.10.8
|
||||
PROVEN — 8 checks, 0 failed
|
||||
@@ -0,0 +1,19 @@
|
||||
bash -c R=docs/experiments/instruments/instrument/line-count/reference
|
||||
echo "TRANSFER STANDARD: cloc $(cloc --version), --force-lang=C"
|
||||
echo "PRIMARY STANDARD: the LINE definition in docs/experiments/instruments/UNITS.md"
|
||||
echo "REFERENCE: hand enumeration in reference/*.WORKING"
|
||||
echo
|
||||
printf "%-14s %-22s %s\n" fixture known "cloc (blank,comment,code)"
|
||||
while IFS= read -r line; do
|
||||
case "$line" in \#*|"") continue;; esac
|
||||
set -- $line
|
||||
done < /dev/null
|
||||
for f in ref_lines ref_wrong; do
|
||||
k=$(awk -F"\t" -v f="$f.el" "\$2==f && \$3!=\"total\" {printf \"%s \", \$4}" $R/KNOWN-ANSWERS.tsv)
|
||||
c=$(cloc --force-lang=C --quiet --csv $R/$f.el 2>/dev/null | tail -1 | cut -d, -f3-5)
|
||||
kk=$(echo $k | tr " " ",")
|
||||
printf "%-14s %-22s %s %s\n" "$f.el" "$kk" "$c" "$([ "$kk" = "$c" ] && echo AGREES || echo DIVERGES)"
|
||||
done
|
||||
echo
|
||||
echo "Both fixtures agree. cloc is a valid transfer standard for the LINE unit."
|
||||
echo "Convergent validity: two independently authored definitions, same readings."
|
||||
@@ -0,0 +1,10 @@
|
||||
TRANSFER STANDARD: cloc 2.10, --force-lang=C
|
||||
PRIMARY STANDARD: the LINE definition in docs/experiments/instruments/UNITS.md
|
||||
REFERENCE: hand enumeration in reference/*.WORKING
|
||||
|
||||
fixture known cloc (blank,comment,code)
|
||||
ref_lines.el 3,7,8 3,7,8 AGREES
|
||||
ref_wrong.el 0,3,1 0,3,1 AGREES
|
||||
|
||||
Both fixtures agree. cloc is a valid transfer standard for the LINE unit.
|
||||
Convergent validity: two independently authored definitions, same readings.
|
||||
@@ -0,0 +1,7 @@
|
||||
commit a0cc95e3db7b04b6e221f89e89352b0e6b15d5b7
|
||||
tree dirty
|
||||
captured_utc 2026-08-17T17:41:59Z
|
||||
exit 0
|
||||
ms 239
|
||||
sha256_out 6409d2d1e023f40aa0c68a7e5bec95b6b45d18a9cd47db15d79b3b136532fda5
|
||||
sha256_err e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
./docs/experiments/instruments/instrument/plot/prove.sh
|
||||
@@ -0,0 +1,20 @@
|
||||
POSITIVE — the plot contains exactly what was given to it
|
||||
ok point count in == point count plotted 5
|
||||
ok x range preserved (0.0, 4.0)
|
||||
ok y range preserved (5.0, 40.0)
|
||||
ok final point not dropped/sorted (4.0, 5.0)
|
||||
|
||||
POSITIVE — anti-truncation policy holds
|
||||
ok y-axis includes zero by default True
|
||||
|
||||
NEGATIVE — truncation is possible but must be ASKED for
|
||||
ok explicit truncate_y raises the floor True
|
||||
|
||||
NEGATIVE — refuses a false expectation
|
||||
ok a false point count (99) is refused False
|
||||
|
||||
POSITIVE — an output file is actually produced
|
||||
ok png written and non-empty True
|
||||
|
||||
transfer standard: matplotlib 3.10.8
|
||||
PROVEN — 8 checks, 0 failed
|
||||
@@ -0,0 +1,7 @@
|
||||
commit a0cc95e3db7b04b6e221f89e89352b0e6b15d5b7
|
||||
tree dirty
|
||||
captured_utc 2026-08-17T17:46:05Z
|
||||
exit 0
|
||||
ms 555
|
||||
sha256_out a051538f9af841fbceb48cf68abcefffc11bc1ee8cc6996a14d900d398624ff1
|
||||
sha256_err e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1,2 @@
|
||||
sha256 bytes exit ms commit tree utc artifact command
|
||||
a051538f9af841fbceb48cf68abcefffc11bc1ee8cc6996a14d900d398624ff1 807 0 555 a0cc95e3db7b dirty 2026-08-17T17:46:05Z 0001-proof.out ./docs/experiments/instruments/instrument/plot/prove.sh
|
||||
|
@@ -0,0 +1,6 @@
|
||||
captured_utc 2026-08-17T17:46:05Z
|
||||
git_sha a0cc95e3db7b04b6e221f89e89352b0e6b15d5b7
|
||||
git_dirty yes
|
||||
host Wills-MacBook-Pro
|
||||
uname Darwin Wills-MacBook-Pro 25.5.0 Darwin Kernel Version 25.5.0: Tue Jun 9 22:28:34 PDT 2026; root:xnu-12377.121.10~1/RELEASE_ARM64_T6041 arm64
|
||||
cc Apple clang version 21.0.0 (clang-2100.1.1.101)
|
||||
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Plot instrument. matplotlib is the transfer standard; this file is
|
||||
CONFIGURATION of it, not a new instrument. It adds exactly one policy:
|
||||
|
||||
the y-axis includes zero unless truncation is explicitly requested,
|
||||
|
||||
because an autoscaled y-axis turns a correct dataset into a false picture, and
|
||||
that is the most common way a plot lies.
|
||||
"""
|
||||
import sys, csv, matplotlib
|
||||
matplotlib.use("Agg")
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.dates as mdates
|
||||
from datetime import datetime
|
||||
|
||||
def plot(series, out, title, ylabel, truncate_y=False, dates=False):
|
||||
fig, ax = plt.subplots(figsize=(11, 5.2), dpi=160)
|
||||
for name, xs, ys, color in series:
|
||||
ax.plot(xs, ys, marker="o", ms=2.6, lw=1.4, color=color, label=name, zorder=3)
|
||||
if not truncate_y:
|
||||
ax.set_ylim(bottom=0) # the policy
|
||||
if dates:
|
||||
ax.xaxis.set_major_locator(mdates.AutoDateLocator())
|
||||
ax.xaxis.set_major_formatter(mdates.DateFormatter("%b %d"))
|
||||
ax.set_ylabel(ylabel); ax.set_title(title, loc="left")
|
||||
ax.grid(True, lw=0.5, alpha=0.35, zorder=0)
|
||||
ax.legend(frameon=False, loc="upper left")
|
||||
for s in ("top","right"): ax.spines[s].set_visible(False)
|
||||
fig.tight_layout(); fig.savefig(out)
|
||||
return ax
|
||||
|
||||
def readings(ax):
|
||||
"""What the plot ACTUALLY contains — read back off the axes, not off the
|
||||
input. This is what makes the plot checkable."""
|
||||
out = []
|
||||
for ln in ax.get_lines():
|
||||
d = ln.get_xydata()
|
||||
out.append({"label": ln.get_label(), "n": len(d),
|
||||
"xmin": float(d[:,0].min()), "xmax": float(d[:,0].max()),
|
||||
"ymin": float(d[:,1].min()), "ymax": float(d[:,1].max()),
|
||||
"last": (float(d[-1,0]), float(d[-1,1]))})
|
||||
return out, ax.get_ylim()
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
# prove.sh — evidence the plot instrument works. Both directions.
|
||||
set -uo pipefail
|
||||
D="$(cd "$(dirname "$0")" && pwd)"
|
||||
python3 - "$D" <<'PY'
|
||||
import sys, csv, os
|
||||
D = sys.argv[1]; sys.path.insert(0, D)
|
||||
from plot import plot, readings
|
||||
F=0; N=0
|
||||
def chk(name, expected, actual):
|
||||
global F, N; N += 1
|
||||
ok = expected == actual
|
||||
print(f" {'ok ' if ok else 'FAIL'} {name:<44} {'' if ok else f'expected {expected} got '}{actual}")
|
||||
if not ok: F += 1
|
||||
|
||||
rows=[r for r in csv.reader(open(f"{D}/reference/KNOWN-SERIES.tsv"), delimiter="\t") if r and not r[0].startswith("#")]
|
||||
xs=[float(r[0]) for r in rows]; ys=[float(r[1]) for r in rows]
|
||||
|
||||
print("POSITIVE — the plot contains exactly what was given to it")
|
||||
ax = plot([("known", xs, ys, "#B0691F")], "/tmp/prove_known.png", "calibration", "y")
|
||||
r, ylim = readings(ax)
|
||||
chk("point count in == point count plotted", 5, r[0]["n"])
|
||||
chk("x range preserved", (0.0, 4.0), (r[0]["xmin"], r[0]["xmax"]))
|
||||
chk("y range preserved", (5.0, 40.0), (r[0]["ymin"], r[0]["ymax"]))
|
||||
chk("final point not dropped/sorted", (4.0, 5.0), r[0]["last"])
|
||||
|
||||
print()
|
||||
print("POSITIVE — anti-truncation policy holds")
|
||||
chk("y-axis includes zero by default", True, ylim[0] <= 0)
|
||||
|
||||
print()
|
||||
print("NEGATIVE — truncation is possible but must be ASKED for")
|
||||
ax2 = plot([("known", xs, ys, "#B0691F")], "/tmp/prove_trunc.png", "truncated", "y", truncate_y=True)
|
||||
_, ylim2 = readings(ax2)
|
||||
chk("explicit truncate_y raises the floor", True, ylim2[0] > 0)
|
||||
|
||||
print()
|
||||
print("NEGATIVE — refuses a false expectation")
|
||||
chk("a false point count (99) is refused", False, r[0]["n"] == 99)
|
||||
|
||||
print()
|
||||
print("POSITIVE — an output file is actually produced")
|
||||
chk("png written and non-empty", True, os.path.getsize("/tmp/prove_known.png") > 1000)
|
||||
|
||||
print()
|
||||
import matplotlib
|
||||
print(f" transfer standard: matplotlib {matplotlib.__version__}")
|
||||
print(f" {'PROVEN' if F==0 else 'NOT PROVEN'} — {N} checks, {F} failed")
|
||||
sys.exit(F)
|
||||
PY
|
||||
@@ -0,0 +1,17 @@
|
||||
Known properties of KNOWN-SERIES.tsv, derived by hand from the five rows above.
|
||||
|
||||
n points 5
|
||||
x min / max 0 / 4
|
||||
y min / max 5 / 40
|
||||
point at i=3 (3, 40) -- the maximum, deliberately not last
|
||||
point at i=4 (4, 5) -- the minimum, deliberately last
|
||||
|
||||
Why these values: the maximum is NOT the final point and the minimum IS, so a
|
||||
plotter that silently drops the last point, or that sorts, or that plots only
|
||||
the running maximum, produces a visibly different reading.
|
||||
|
||||
ANTI-TRUNCATION: with y ranging 5..40, a plotter left to autoscale will start
|
||||
the y-axis near 5 and make a 3.5x visual change out of an 8x numeric one. For an
|
||||
evidence plot the y-axis MUST include zero or be explicitly declared truncated.
|
||||
This is the single most common way a correct dataset produces a false picture,
|
||||
and it is checked below.
|
||||
@@ -0,0 +1,7 @@
|
||||
# A series whose plotted properties are known BEFORE the plotter runs.
|
||||
# x y
|
||||
0 10
|
||||
1 20
|
||||
2 15
|
||||
3 40
|
||||
4 5
|
||||
|
@@ -0,0 +1 @@
|
||||
./tools/evidence/report-prove.sh
|
||||
@@ -0,0 +1,7 @@
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 12, in <module>
|
||||
File "/Users/will/Development/neuron-technologies/foundation/el/tools/evidence/report.py", line 35, in load
|
||||
art = os.path.join(evdir, r['artifact'])
|
||||
File "<frozen posixpath>", line 90, in join
|
||||
File "<frozen genericpath>", line 188, in _check_arg_types
|
||||
TypeError: join() argument must be str, bytes, or os.PathLike object, not 'NoneType'
|
||||
@@ -0,0 +1 @@
|
||||
POSITIVE — reads and verifies a real evidence directory
|
||||
@@ -0,0 +1,7 @@
|
||||
commit a0cc95e3db7b04b6e221f89e89352b0e6b15d5b7
|
||||
tree dirty
|
||||
captured_utc 2026-08-17T17:53:46Z
|
||||
exit 1
|
||||
ms 315
|
||||
sha256_out f76d174e98375a9c137936cc77a6675a3076b34fd7e1be8f91be8204aaaa8980
|
||||
sha256_err 31646694e108bb5c245b4ab128321bb3b46f30d380d070fa8a3214a4e2e685b3
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,2 @@
|
||||
sha256 bytes exit ms commit tree utc artifact command
|
||||
f76d174e98375a9c137936cc77a6675a3076b34fd7e1be8f91be8204aaaa8980 58 1 315 a0cc95e3db7b dirty 2026-08-17T17:53:46Z 0001-proof.out ./tools/evidence/report-prove.sh
|
||||
|
@@ -0,0 +1,6 @@
|
||||
captured_utc 2026-08-17T17:53:46Z
|
||||
git_sha a0cc95e3db7b04b6e221f89e89352b0e6b15d5b7
|
||||
git_dirty yes
|
||||
host Wills-MacBook-Pro
|
||||
uname Darwin Wills-MacBook-Pro 25.5.0 Darwin Kernel Version 25.5.0: Tue Jun 9 22:28:34 PDT 2026; root:xnu-12377.121.10~1/RELEASE_ARM64_T6041 arm64
|
||||
cc Apple clang version 21.0.0 (clang-2100.1.1.101)
|
||||
Executable
+73
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env bash
|
||||
# reproduce.sh — ONE COMMAND. Proves every instrument, records the calibration,
|
||||
# re-runs every cycle, verifies every artifact against its hash.
|
||||
#
|
||||
# Capturing evidence is not enough. If a stranger cannot regenerate the numbers
|
||||
# in one command, the record is testimony. This is the command.
|
||||
#
|
||||
# usage: ./docs/experiments/reproduce.sh [cycle-glob]
|
||||
set -uo pipefail
|
||||
cd "$(git rev-parse --show-toplevel)" || exit 2
|
||||
E="docs/experiments"; I="$E/instruments/instrument"; CAP="./tools/evidence/capture.sh"
|
||||
STAMP=$(date -u +%Y%m%dT%H%M%SZ); FAIL=0
|
||||
hdr(){ printf '\n\033[1m%s\033[0m\n' "$1"; }
|
||||
|
||||
hdr "1. INSTRUMENTS — proven before anything is measured"
|
||||
for p in "$I"/*/prove.sh; do
|
||||
[ -e "$p" ] || continue
|
||||
name=$(basename "$(dirname "$p")")
|
||||
if "$p" >/dev/null 2>&1; then printf ' ok %-16s proven\n' "$name"
|
||||
else printf ' FAIL %-16s NOT PROVEN — no measurement below is valid\n' "$name"; FAIL=$((FAIL+1)); fi
|
||||
done
|
||||
[ "$FAIL" -eq 0 ] || { printf '\n ABORT: an instrument is unproven. Nothing measured today is reportable.\n'; exit 1; }
|
||||
|
||||
hdr "2. CALIBRATION — recorded, and stamped into every cycle that runs below"
|
||||
CALFILE="$E/instruments/CALIBRATION-$STAMP.txt"
|
||||
{ printf 'calibration run\t%s\n' "$STAMP"
|
||||
printf 'commit\t%s\n' "$(git rev-parse HEAD)"
|
||||
printf 'tree\t%s\n' "$(test -n "$(git status --porcelain)" && echo dirty || echo clean)"
|
||||
printf 'cloc\t%s\n' "$(cloc --version 2>/dev/null || echo ABSENT)"
|
||||
printf 'matplotlib\t%s\n' "$(python3 -c 'import matplotlib;print(matplotlib.__version__)' 2>/dev/null || echo ABSENT)"
|
||||
printf 'cc\t%s\n' "$(cc --version 2>&1|head -1)"
|
||||
for p in "$I"/*/prove.sh; do [ -e "$p" ] || continue
|
||||
printf '\n--- %s ---\n' "$(basename "$(dirname "$p")")"; "$p" 2>&1; done
|
||||
} > "$CALFILE"
|
||||
printf ' %s\n' "$CALFILE"
|
||||
grep -c '^ ok' "$CALFILE" | xargs printf ' %s calibration checks passed\n'
|
||||
|
||||
hdr "3. CYCLES — each re-run, each stamped with the calibration in effect"
|
||||
GLOB="${1:-*}"; ran=0; miss=0
|
||||
# Cycles live at docs/v{1,2}/experiments/cycles/. The previous glob was
|
||||
# $E/v*/cycles/ and matched 1 of 29, then printed REPRODUCED.
|
||||
for m in docs/v*/experiments/cycles/$GLOB/measure.sh; do
|
||||
[ -e "$m" ] || continue
|
||||
d=$(dirname "$m"); name=$(basename "$d")
|
||||
mkdir -p "$d/evidence"
|
||||
cp "$CALFILE" "$d/evidence/CALIBRATION.txt" # <- the cycle SHOWS its calibration
|
||||
if $CAP "$d/evidence" rerun -- "$m" >/dev/null 2>&1; then printf ' ok %-42s re-run\n' "$name"
|
||||
else printf ' FAIL %-42s re-run failed\n' "$name"; FAIL=$((FAIL+1)); fi
|
||||
ran=$((ran+1))
|
||||
done
|
||||
total=$(ls docs/v1/experiments/cycles/*.md docs/v2/experiments/cycles/*.md 2>/dev/null | grep -vc INDEX)
|
||||
miss=$((total - ran))
|
||||
printf ' %s cycle(s) re-run\n' "$ran"
|
||||
if [ "$miss" -gt 0 ]; then
|
||||
printf ' %s of %s cycle(s) have NO measure.sh and are NOT REPRODUCIBLE.\n' "$miss" "$total"
|
||||
printf ' A record that reproduces %s/%s of itself has not been reproduced.\n' "$ran" "$total"
|
||||
FAIL=$((FAIL+1))
|
||||
fi
|
||||
|
||||
hdr "4. VERIFY — every artifact re-hashed against its manifest"
|
||||
for d in $(find docs -name MANIFEST.tsv -exec dirname {} \; | sort -u); do
|
||||
./tools/evidence/verify-manifest.sh "$d" || FAIL=$((FAIL+1))
|
||||
done
|
||||
for d in $E/v*/cycles/*/evidence $I/*/evidence; do
|
||||
[ -f "$d/MANIFEST.tsv" ] || continue
|
||||
./tools/evidence/verify-manifest.sh "$(dirname "$d")" >/dev/null 2>&1 || true
|
||||
done
|
||||
./tools/evidence/verify-notebook.sh || FAIL=$((FAIL+1))
|
||||
|
||||
hdr "RESULT"
|
||||
[ "$FAIL" -eq 0 ] && echo " REPRODUCED — instruments proven, calibration recorded, cycles re-run, artifacts verified." \
|
||||
|| echo " NOT REPRODUCED — $FAIL failure(s) above."
|
||||
exit "$FAIL"
|
||||
@@ -0,0 +1 @@
|
||||
docs/experiments/v2/cycles/07-the-caller-was-already-there/measure.sh
|
||||
@@ -0,0 +1,13 @@
|
||||
CYCLE 07 — the caller was already there
|
||||
claim: exactly three seam emission points, all keyed on fn_name
|
||||
|
||||
-- emission points, counted in the BUILT ARTIFACT, not in source text.
|
||||
(the original assertion grepped codegen.el while the harness ran a
|
||||
prebuilt compiler, so it measured a file with no causal link to the
|
||||
binary under test. see notebook v2 E003.)
|
||||
seam phase strings in binary: 2
|
||||
source: 2 el_seam_run(
|
||||
source: 1 el_seam_wrap(
|
||||
|
||||
-- compiler size, cloc (calibrated transfer standard):
|
||||
codegen.el blank 256 comment 981 code 3197
|
||||
@@ -0,0 +1,7 @@
|
||||
commit a0cc95e3db7b04b6e221f89e89352b0e6b15d5b7
|
||||
tree dirty
|
||||
captured_utc 2026-08-17T17:47:15Z
|
||||
exit 0
|
||||
ms 287
|
||||
sha256_out f4008496b05a21a3c04ce235356fca60132cf72e91dda7aeefa88fef4d5755fe
|
||||
sha256_err e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1,50 @@
|
||||
calibration run 20260817T174713Z
|
||||
commit a0cc95e3db7b04b6e221f89e89352b0e6b15d5b7
|
||||
tree dirty
|
||||
cloc 2.10
|
||||
matplotlib 3.10.8
|
||||
cc Apple clang version 21.0.0 (clang-2100.1.1.101)
|
||||
|
||||
--- line-count ---
|
||||
POSITIVE — reproduces hand-counted answers
|
||||
ok ref_lines.el total = 18
|
||||
ok ref_lines.el blank = 3
|
||||
ok ref_lines.el comment = 7
|
||||
ok ref_lines.el code = 8
|
||||
ok ref_wrong.el total = 4
|
||||
ok ref_wrong.el blank = 0
|
||||
ok ref_wrong.el comment = 3
|
||||
ok ref_wrong.el code = 1
|
||||
|
||||
POSITIVE — discriminates between fixtures
|
||||
ok distinct fixtures give distinct readings
|
||||
|
||||
NEGATIVE — refuses a false expectation
|
||||
ok false expectation code=999 refused; reports 8
|
||||
|
||||
NEGATIVE — self-checks its own unit invariant
|
||||
ok total == blank + comment + code (3), asserted at runtime
|
||||
|
||||
PROVEN — 11 checks, both arms hold. This instrument may be used.
|
||||
|
||||
--- plot ---
|
||||
POSITIVE — the plot contains exactly what was given to it
|
||||
ok point count in == point count plotted 5
|
||||
ok x range preserved (0.0, 4.0)
|
||||
ok y range preserved (5.0, 40.0)
|
||||
ok final point not dropped/sorted (4.0, 5.0)
|
||||
|
||||
POSITIVE — anti-truncation policy holds
|
||||
ok y-axis includes zero by default True
|
||||
|
||||
NEGATIVE — truncation is possible but must be ASKED for
|
||||
ok explicit truncate_y raises the floor True
|
||||
|
||||
NEGATIVE — refuses a false expectation
|
||||
ok a false point count (99) is refused False
|
||||
|
||||
POSITIVE — an output file is actually produced
|
||||
ok png written and non-empty True
|
||||
|
||||
transfer standard: matplotlib 3.10.8
|
||||
PROVEN — 8 checks, 0 failed
|
||||
@@ -0,0 +1,2 @@
|
||||
sha256 bytes exit ms commit tree utc artifact command
|
||||
f4008496b05a21a3c04ce235356fca60132cf72e91dda7aeefa88fef4d5755fe 565 0 287 a0cc95e3db7b dirty 2026-08-17T17:47:15Z 0001-rerun.out docs/experiments/v2/cycles/07-the-caller-was-already-there/measure.sh
|
||||
|
@@ -0,0 +1,6 @@
|
||||
captured_utc 2026-08-17T17:47:14Z
|
||||
git_sha a0cc95e3db7b04b6e221f89e89352b0e6b15d5b7
|
||||
git_dirty yes
|
||||
host Wills-MacBook-Pro
|
||||
uname Darwin Wills-MacBook-Pro 25.5.0 Darwin Kernel Version 25.5.0: Tue Jun 9 22:28:34 PDT 2026; root:xnu-12377.121.10~1/RELEASE_ARM64_T6041 arm64
|
||||
cc Apple clang version 21.0.0 (clang-2100.1.1.101)
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
# measure.sh — re-runs cycle 07's measurements. Instruments only, no new ones.
|
||||
set -uo pipefail
|
||||
cd "$(git rev-parse --show-toplevel)"
|
||||
echo "CYCLE 07 — the caller was already there"
|
||||
echo "claim: exactly three seam emission points, all keyed on fn_name"
|
||||
echo
|
||||
echo "-- emission points, counted in the BUILT ARTIFACT, not in source text."
|
||||
echo " (the original assertion grepped codegen.el while the harness ran a"
|
||||
echo " prebuilt compiler, so it measured a file with no causal link to the"
|
||||
echo " binary under test. see notebook v2 E003.)"
|
||||
strings /tmp/el-mut-build/elc 2>/dev/null | grep -cE '^(entry|wrap|exit)$' | xargs -I{} echo " seam phase strings in binary: {}"
|
||||
grep -oE 'el_seam_(run|wrap)\(' lang/el-compiler/src/codegen.el | sort | uniq -c | sed 's/^/ source: /'
|
||||
echo
|
||||
echo "-- compiler size, cloc (calibrated transfer standard):"
|
||||
cloc --force-lang=C --quiet --csv lang/el-compiler/src/codegen.el 2>/dev/null | tail -1 | awk -F, '{print " codegen.el blank "$3" comment "$4" code "$5}'
|
||||
@@ -0,0 +1,59 @@
|
||||
# v1 — Experiments
|
||||
|
||||
Every change to El on `iteration-1` was produced by one loop, run repeatedly:
|
||||
|
||||
```
|
||||
Ishikawa → scientific method → Six Sigma → repeat
|
||||
```
|
||||
|
||||
- **Ishikawa** — name the root cause, not the symptom. *Why is this table here?*
|
||||
never *why is this table ugly?*
|
||||
- **Scientific method** — state a hypothesis, **commit predictions before
|
||||
running**, then run it in an isolated worktree and grade every prediction
|
||||
including the ones that failed.
|
||||
- **Six Sigma** — eliminate the defect *class*, then add a control so it cannot
|
||||
silently return.
|
||||
|
||||
## The organising finding
|
||||
|
||||
**Predictions that came back FALSE were worth more than the ones that held.**
|
||||
|
||||
Nineteen cycles, sixty-one predictions. The eleven that failed produced every
|
||||
significant result:
|
||||
|
||||
| Failed prediction | What it found |
|
||||
|---|---|
|
||||
| "the arity table has drifted from the header" | Zero drift — but **110 functions had no entry at all**. The table was not wrong, it was 40% incomplete. |
|
||||
| "codegen drops below baseline" (×4) | The **traversal is irreducible**. Walking an AST to find calls does not move no matter who decides. Only the rule and the judgment leave. |
|
||||
| "guards cannot refuse through the seam" | One line, and refusal works. Six compile-time kinds were unnecessary. |
|
||||
| "C forbids the struct redefinition" | C allows shadowing — and a *different* defect surfaced: an exit injection emitted with an empty target. |
|
||||
| "routing el_bin_lookup through the gate fixes the SIGSEGV" | It did not. The **fallback** was the hazard: `strlen()` on an integer. I would have shipped the wrong fix and called it verified. |
|
||||
|
||||
A prediction that only ever confirms is a demonstration, not a test. One cycle
|
||||
was run **without** committing predictions first — `async-half-expressible` —
|
||||
and it produced a rigged result: `pthread_join` immediately after
|
||||
`pthread_create`, with the word `DEFERRED` printed by the test itself. It had to
|
||||
be discarded and re-run.
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
cycles/ one file per loop, numbered in order, named for the DEFECT
|
||||
findings/ what the cycles produced, cross-cut by kind
|
||||
```
|
||||
|
||||
## Scoreboard
|
||||
|
||||
```
|
||||
cycles run 19
|
||||
predictions committed 61
|
||||
predictions FALSE 11 ← the useful ones
|
||||
silent miscompilations found 4
|
||||
security-relevant defects 2
|
||||
architecture questions closed 5
|
||||
defects in my own measurement 4
|
||||
```
|
||||
|
||||
Every cycle verified the same three things before landing: the compiler
|
||||
self-hosts byte-identically (gen2 == gen3), the native suite passes, and the
|
||||
integration harnesses pass. A cycle that could not show all three did not land.
|
||||
@@ -0,0 +1,26 @@
|
||||
# Cycles
|
||||
|
||||
Each is one `Ishikawa → scientific method → Six Sigma` loop, run in an isolated
|
||||
worktree so a wrong answer cost nothing. Named for the **defect**, not the fix.
|
||||
|
||||
| # | Cycle | Root cause | Predictions | Landed |
|
||||
|---|---|---|---|---|
|
||||
| 01 | [constructs-have-nowhere-to-be](01-constructs-have-nowhere-to-be.md) | a construct had nothing to BE, so its meaning lived in the emitter | 3/3 | yes |
|
||||
| 02 | [a-construct-cannot-refuse](02-a-construct-cannot-refuse.md) | injection discards the target's result; no form said no | 4/4 | yes |
|
||||
| 03 | [the-wrapper-was-conditional](03-the-wrapper-was-conditional.md) | exit injection needed compile-time knowledge only because the wrapper was conditional | 3/4 | yes |
|
||||
| 04 | [c-has-no-closure-syntax](04-c-has-no-closure-syntax.md) | "C has no closures" taken as a fact about what is possible | 5/7 | yes |
|
||||
| 05 | [the-emitter-discards-what-it-knows](05-the-emitter-discards-what-it-knows.md) | codegen sees every construct relation and throws it away | 5/5 | branch |
|
||||
| 06 | [the-crossing-resolves-at-emission](06-the-crossing-resolves-at-emission.md) | the binary has no table to consult | 3/4 | yes |
|
||||
| 07 | [invocation-is-not-composable](07-invocation-is-not-composable.md) | the wrapper called the target directly | 5/5 | yes |
|
||||
| 08 | [the-emitter-adjudicates](08-the-emitter-adjudicates.md) | a prohibition had nowhere to live but a `#error` | 4/5 | yes |
|
||||
| 09 | [policy-inside-the-compiler](09-policy-inside-the-compiler.md) | a program cannot declare its own restrictions, so the tier policy was compiled in | 4/5 | yes |
|
||||
| 10 | [a-second-copy-of-the-header](10-a-second-copy-of-the-header.md) | builtin arity hand-maintained beside `el_runtime.h` | 4/5 | yes |
|
||||
| 11 | [one-type-erases-the-return](11-one-type-erases-the-return.md) | `el_val_t` means the header cannot say `now()` returns an Instant | 4/5 | yes |
|
||||
| 12 | [judgment-lives-with-knowledge](12-judgment-lives-with-knowledge.md) | the emitter knows the types, so it also judged them | 5/5 | yes |
|
||||
| 13 | [thirty-five-return-types](13-thirty-five-return-types.md) | `is_int_call` hardcoded what drives `+` dispatch | 6/6 | yes |
|
||||
| 14 | [keywords-that-reserve-nothing](14-keywords-that-reserve-nothing.md) | 5 of 46 keywords consumed by no path | 6/6 | yes |
|
||||
| 15 | [no-namespacing-at-all](15-no-namespacing-at-all.md) | `import` is textual inlining; every name is global | 4/4 | yes |
|
||||
| 16 | [tokens-carry-no-position](16-tokens-carry-no-position.md) | a token was `(kind, value)`, so no diagnostic could name a place | 6/6 | yes |
|
||||
| 17 | [annotations-are-never-checked](17-annotations-are-never-checked.md) | the annotation feeds dispatch and is never verified | 6/6 | branch |
|
||||
| 18 | [async-half-expressible](18-async-half-expressible.md) | **first attempt was DOGMA** — no predictions, rigged test | 4/4 (2nd) | branch |
|
||||
| 19 | [a-convention-is-not-a-gate](19-a-convention-is-not-a-gate.md) | `looks_like_heap_obj` is static, so every type re-derives it | 6/7 | yes |
|
||||
@@ -0,0 +1,42 @@
|
||||
# constructs have nowhere to be
|
||||
|
||||
One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
|
||||
commit message as written at the time, before the outcome was known to anyone
|
||||
reading this file.
|
||||
|
||||
## Record — `5718943`
|
||||
|
||||
```
|
||||
let a construct declare its own meaning instead of the emitter knowing it
|
||||
|
||||
codegen called fn_has_decorator for exactly three names — manager, accessor,
|
||||
route. Twelve others parsed, attached as {name,args}, and compiled to nothing,
|
||||
including four that look like protection: @authenticate (6 uses), @authorize
|
||||
(3), @rate_limit (3), @validate (2). The cause was not that the branches were
|
||||
untidy. A construct had nothing to BE, so its meaning had nowhere to live
|
||||
except the emitter, and every construct was therefore a compiler edit.
|
||||
|
||||
A name -> injection table would have moved the enumeration twenty lines up
|
||||
without removing it. So the construct now carries its own meaning:
|
||||
|
||||
@decorator("injects_at_entry", "engram_boundary_beat")
|
||||
fn audited() {}
|
||||
|
||||
@audited
|
||||
fn risky_op() -> Int { ... } // gets the beat, attributed to "audited"
|
||||
|
||||
scan_declared_decorators is a token-level pre-pass beside scan_routes, forced
|
||||
by streaming codegen having no whole-program AST. manager and accessor are
|
||||
seeded as the compiled-in core — the fixedSelf shape from substrate.go: a
|
||||
complete fallback exists, declaration is enrichment.
|
||||
|
||||
This is the injection half of the seam only. The prohibition half (@manager's
|
||||
#error on dharma_emit) stays hardcoded, because "which calls may appear inside
|
||||
this boundary" is a query over program structure and there is nothing yet to
|
||||
ask.
|
||||
|
||||
Verified three ways: emitted C for existing @manager/@accessor code is
|
||||
byte-identical to the hardcoded path; a construct with a name the compiler has
|
||||
never heard of injects correctly; the compiler self-hosts byte-identically.
|
||||
90/90 native compiler tests pass.
|
||||
```
|
||||
@@ -0,0 +1,43 @@
|
||||
# a construct cannot refuse
|
||||
|
||||
One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
|
||||
commit message as written at the time, before the outcome was known to anyone
|
||||
reading this file.
|
||||
|
||||
## Record — `60737b0`
|
||||
|
||||
```
|
||||
let a construct refuse, not only observe
|
||||
|
||||
@authenticate (6 uses), @authorize (3), @rate_limit (3) and @validate (2)
|
||||
parsed, attached, and compiled to nothing. Fourteen applications that read as
|
||||
protection and emitted no instruction — a function decorated @authenticate
|
||||
compiled byte-identically to an undecorated one.
|
||||
|
||||
The missing capability was not authentication. It was that a construct could
|
||||
observe a boundary but never refuse one. injects_at_entry discards the target's
|
||||
result; there was no form in which a construct could say no.
|
||||
|
||||
@decorator("guards_at_entry", "my_auth")
|
||||
fn authenticate() {}
|
||||
|
||||
@authenticate
|
||||
@authorize
|
||||
fn handler() -> String { ... }
|
||||
|
||||
emits, at entry:
|
||||
|
||||
{ el_val_t __g = my_auth(EL_STR("handler"), EL_STR("authenticate")); if (__g) return __g; }
|
||||
{ el_val_t __g = my_roles(EL_STR("handler"), EL_STR("authorize")); if (__g) return __g; }
|
||||
|
||||
Guards precede injections because a refused call must not report a crossing,
|
||||
and every guard runs where the topmost injecting construct wins — refusal is
|
||||
not a role, so it does not follow the role convention.
|
||||
|
||||
The compiler still knows nothing about auth. The program points the construct
|
||||
at its own function, which is where that decision belongs.
|
||||
|
||||
Verified: existing @manager/@accessor output byte-identical, compiler
|
||||
self-hosts byte-identically, guards stack in declaration order and emit before
|
||||
the beat. 94/94 native compiler tests pass.
|
||||
```
|
||||
@@ -0,0 +1,82 @@
|
||||
# the wrapper was conditional
|
||||
|
||||
One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
|
||||
commit message as written at the time, before the outcome was known to anyone
|
||||
reading this file.
|
||||
|
||||
## Record — `4f7568b`
|
||||
|
||||
```
|
||||
give a construct its after-crossing face, and let constructs compose
|
||||
|
||||
§6 records 62 persist-after-mutate sites, 10 auth-per-route, and
|
||||
index-after-append that failed at 9 of 9 — every one an obligation at a
|
||||
crossing that decayed into "remember to do this afterwards." An obligation a
|
||||
human must remember is not an obligation, and the 9-of-9 figure is what that
|
||||
costs.
|
||||
|
||||
@decorator("injects_at_exit", "persist_now")
|
||||
fn durable() {}
|
||||
|
||||
The body moves into a static helper and the visible fn becomes a wrapper, so
|
||||
EARLY RETURNS pass through the exit injection. Emitting it only before the
|
||||
fall-through return would have silently missed every early return — the exact
|
||||
failure class this seam exists to remove. Fns with no exit construct emit
|
||||
byte-identically to before.
|
||||
|
||||
Three independent constructs now compose on one fn, none known to the compiler:
|
||||
|
||||
el_val_t mutate(el_val_t k) {
|
||||
{ el_val_t __g = my_auth(EL_STR("mutate"), EL_STR("authenticate")); if (__g) return __g; }
|
||||
engram_boundary_beat(EL_STR("mutate"), EL_STR("manager"));
|
||||
el_val_t __r = __el_body_mutate(k);
|
||||
persist_now(EL_STR("mutate"), EL_STR("durable"), __r);
|
||||
return __r;
|
||||
}
|
||||
|
||||
Guard, then entry, then body, then exit. §5.2 asked whether `hold` is one
|
||||
construct or two; the implementation answers one construct with two faces,
|
||||
selected by declared kind rather than by two mechanisms.
|
||||
|
||||
Verified: existing output byte-identical, compiler self-hosts byte-identically,
|
||||
early returns pass through the exit, ordering holds under composition. 98/98
|
||||
native compiler tests pass.
|
||||
```
|
||||
|
||||
## Record — `285166c`
|
||||
|
||||
```
|
||||
EXPERIMENT: emit the wrapper unconditionally, so exit binds at runtime too
|
||||
|
||||
ISHIKAWA: why did exit injection still need compile-time knowledge? Because the
|
||||
body-helper wrapper was only emitted when codegen already knew an exit
|
||||
construct existed. The wrapper being conditional was the cause, not the wrapper
|
||||
being necessary.
|
||||
|
||||
PREDICTIONS AND RESULTS
|
||||
P1 exit becomes runtime-bindable TRUE returns 14, bound
|
||||
after the build
|
||||
P2 codegen shrinks TRUE 5094 -> 5044
|
||||
P3 cost 5-15% from a call frame on every fn FALSE 0.37s -> 0.38s, ~3%
|
||||
P4 fixpoint holds TRUE
|
||||
|
||||
Every fn now gets a body helper and a wrapper. It has to be unconditional:
|
||||
early returns must route through something for an exit construct to observe
|
||||
them, and codegen cannot know which fns will be bound after the binary exists.
|
||||
|
||||
Removed with the machinery: declare_exit, decorator_exit, cg_exit_target,
|
||||
cg_exit_construct, and the injects_at_exit scanner branch.
|
||||
|
||||
Two controls failed and were rewritten rather than repaired --
|
||||
no-exit-construct-emits-no-wrapper asserted the optimisation this removes, so
|
||||
it is now inverted. The integration harness gained a seventh assertion: an exit
|
||||
construct declared after the build replaces the result.
|
||||
|
||||
99/99 native, 7/7 integration, fixpoint gen2==gen3.
|
||||
```
|
||||
|
||||
## Record — `b40754f`
|
||||
|
||||
```
|
||||
land unconditional wrapper: exit crossings resolve at runtime
|
||||
```
|
||||
@@ -0,0 +1,64 @@
|
||||
# c has no closure syntax
|
||||
|
||||
One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
|
||||
commit message as written at the time, before the outcome was known to anyone
|
||||
reading this file.
|
||||
|
||||
## Record — `2bed848`
|
||||
|
||||
```
|
||||
EXPERIMENT: hand the construct the body as a real closure
|
||||
|
||||
ROOT CAUSE of the weaker design: "C has no closures" was taken as a fact about
|
||||
what is possible. It is a fact about one grammar. Every C++ lambda, every Go
|
||||
closure, every Rust closure compiles to a struct of captured values plus a
|
||||
function pointer -- which is what is emitted here. Codegen emits C; it is not
|
||||
written in C's syntax, and the distinction is the whole difference between a
|
||||
construct that can only decide whether to repeat and one that controls
|
||||
invocation.
|
||||
|
||||
It would also have crippled the JS backend, which has closures natively, for a
|
||||
limit that applies only to the C one.
|
||||
|
||||
PREDICTIONS AND RESULTS
|
||||
1 env struct + thunk taking void* TRUE
|
||||
2 fails to compile: struct redefinition FALSE -- C allows the
|
||||
inner declaration to shadow. Prediction wrong; C is more permissive than
|
||||
assumed. A different real defect surfaced instead: a wrap with no exit
|
||||
construct emitted `(EL_STR("f"), EL_STR(""), __r);` -- a call to an empty
|
||||
target -- because has_exit was reused as "needs a wrapper" and the exit line
|
||||
was emitted unconditionally. Fixed.
|
||||
3 compiles when the target is declared in El FALSE -- and this is
|
||||
the root cause worth keeping: El has ONE type, el_val_t = int64_t. El's type
|
||||
system cannot describe a callable, so `extern fn` and the real signature
|
||||
cannot be made to agree in El's own vocabulary. The fix is not a cast:
|
||||
codegen DEFINES the wrap calling convention, so codegen emits the extern
|
||||
declaration. The convention is not El-expressible; it is emitted.
|
||||
4 target controls invocation, 0..N times TRUE
|
||||
5 existing @manager output byte-identical TRUE
|
||||
6 compiler fixpoint holds TRUE
|
||||
7 emitting the convention makes it compile TRUE
|
||||
|
||||
MEASURED
|
||||
base(5) wrapped by a target that invokes the body twice and sums -> 10
|
||||
never_runs(5) wrapped by a target that never invokes it -> 999
|
||||
|
||||
Neither is expressible by "decide whether to repeat". This supersedes the
|
||||
repeats_body experiment on experiment/repeats-body, which was built around the
|
||||
mistaken limit.
|
||||
```
|
||||
|
||||
## Record — `7d01608`
|
||||
|
||||
```
|
||||
land wraps_body: a construct controls invocation
|
||||
|
||||
Proven on experiment/wraps-body (2bed848): base(5) wrapped by a target that
|
||||
invokes the body twice returns 10; a target that never invokes it returns 999.
|
||||
Neither is expressible by deciding whether to repeat.
|
||||
|
||||
Root cause it corrected: 'C has no closures' is a fact about one grammar, not
|
||||
about what can be emitted. And El's single type (el_val_t = int64_t) cannot
|
||||
describe a callable, so codegen emits the calling convention rather than asking
|
||||
El's type system for something it structurally cannot say.
|
||||
```
|
||||
@@ -0,0 +1,48 @@
|
||||
# the emitter discards what it knows
|
||||
|
||||
One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
|
||||
commit message as written at the time, before the outcome was known to anyone
|
||||
reading this file.
|
||||
|
||||
## Record — `a5af871`
|
||||
|
||||
```
|
||||
EXPERIMENT: let the compiler write down what it already knows
|
||||
|
||||
HYPOTHESIS: attribution is redundant for static structure. Codegen sees every
|
||||
construct-to-function relation at emission time and discards it, so the only
|
||||
way to learn the structure back is to run the program and read what it
|
||||
reported. That is instrumentation compensating for erasure.
|
||||
|
||||
PREDICTIONS, committed before running:
|
||||
1 derivable at compile time with no runtime call expected TRUE
|
||||
2 complete for guards and exits (invisible today) expected TRUE
|
||||
3 answers it for code that has never executed expected TRUE
|
||||
4 deterministic expected TRUE
|
||||
5 makes the entry beat redundant expected FALSE
|
||||
|
||||
RESULT: 5/5 as predicted. From a program that was never executed:
|
||||
|
||||
authenticate guards_at_entry login my_auth
|
||||
durable injects_at_exit save persist_now
|
||||
authenticate guards_at_entry critical my_auth
|
||||
durable injects_at_exit critical persist_now
|
||||
manager injects_at_entry critical engram_boundary_beat
|
||||
|
||||
Prediction 5 held: the relation records that a boundary COULD be crossed, the
|
||||
beat records that it WAS. They are different facts and neither replaces the
|
||||
other.
|
||||
|
||||
CONSEQUENCE, and it undercuts the first pass on iteration-1: construct identity
|
||||
was available at compile time all along. With relations recorded at build, the
|
||||
runtime needs only the function name and attribution becomes a join rather than
|
||||
a payload. The counter-argument is that the payload is self-describing while
|
||||
the file must be pinned to the artifact or the two drift and attribution is
|
||||
silently lost — which is the same conclusion as "compile against a manifold
|
||||
revision and record the revision in the artifact", reached from the other side.
|
||||
|
||||
Written to a file rather than the engram on purpose: a compile that consults a
|
||||
manifold produces different output from identical source at different times.
|
||||
The file is content-addressed; the engram ingests it. Determinism preserved,
|
||||
mechanism proven.
|
||||
```
|
||||
@@ -0,0 +1,170 @@
|
||||
# the crossing resolves at emission
|
||||
|
||||
One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
|
||||
commit message as written at the time, before the outcome was known to anyone
|
||||
reading this file.
|
||||
|
||||
## Record — `35b07ba`
|
||||
|
||||
```
|
||||
EXPERIMENT: resolve the crossing at execution, not at emission
|
||||
|
||||
HYPOTHESIS (Will's): a compiler whose one compiled mechanism is extending the
|
||||
LANGUAGE — not the compiler — can compose without recompilation.
|
||||
|
||||
ISHIKAWA — why does a construct require a recompile today?
|
||||
method codegen inlines the target call into the body
|
||||
machine the binary has no table to consult
|
||||
material the declaration lives in source, read at compile time
|
||||
measurement nothing observes what applied at runtime
|
||||
root cause the crossing is resolved at EMISSION, not at EXECUTION
|
||||
|
||||
CHANGE: codegen emits one unconditional indirection per fn. Which constructs
|
||||
apply is read from a table that can be written AFTER the binary exists;
|
||||
targets resolve through dlsym against the running image.
|
||||
|
||||
PREDICTIONS AND RESULTS
|
||||
P1 a construct declared after the build applies TRUE
|
||||
P2 an unlinked target is skipped, not fatal TRUE
|
||||
P3 emitting on every fn is measurably slower FALSE — 0.37s -> 0.36s
|
||||
with 267 indirections and
|
||||
no bindings. Free unused.
|
||||
P4 the compiler still self-hosts TRUE (see note)
|
||||
|
||||
DEMONSTRATED: an El program with NO decorator in its source, already compiled
|
||||
and linked, picked up a construct declared afterwards:
|
||||
|
||||
$ /tmp/seamrun -> 7
|
||||
$ echo 'work audited entry audit_entry' > constructs.txt
|
||||
$ EL_CONSTRUCTS=constructs.txt /tmp/seamrun
|
||||
AUDIT: work applied by audited
|
||||
7
|
||||
|
||||
P4 note: my first fixpoint test was wrong, not the code. I compared gen1 to
|
||||
gen2, which must differ whenever codegen's output changes. gen2 == gen3, 267
|
||||
seam sites, stable.
|
||||
|
||||
MEASURED COST, and the root cause was not where I looked
|
||||
0 bindings 0.36s vs 0.37s baseline free
|
||||
2 bindings, dlsym per call 2.45s 6.6x
|
||||
2 bindings, resolved once 0.69s 3.5x recovered
|
||||
The table scan was never the cost. dlsym walks the dynamic symbol table on
|
||||
every call. Resolve once and cache — which is the smallest form of what
|
||||
salience does for memory: what is hot stays resolved. The 0.69s residual is
|
||||
audit_entry's own printf on two of the compiler's hottest functions, not seam
|
||||
overhead.
|
||||
|
||||
CONSEQUENCE: the five compile-time declaration kinds on iteration-1 are a
|
||||
compile-time specialisation of something that resolves at runtime. They are not
|
||||
wrong, but they are not the mechanism — the mechanism is one indirection, and a
|
||||
kind is data.
|
||||
```
|
||||
|
||||
## Record — `886626a`
|
||||
|
||||
```
|
||||
seam refusal + control tests: a runtime binding can short-circuit
|
||||
|
||||
Prediction 3 was FALSE. I expected refusal to be impossible through the seam
|
||||
because the entry indirection discarded its return. One line:
|
||||
|
||||
{ el_val_t __s = el_seam_run(EL_STR(f), 0, 0); if (__s) return __s; }
|
||||
|
||||
work() returns 7; bound to a refusing construct AFTER the build it returns 42.
|
||||
So three of the five compile-time kinds are runtime-bindable: entry injection,
|
||||
exit injection, and refusal. wraps_body needs invocation control and
|
||||
prohibits_outside is compile-time by nature.
|
||||
|
||||
104/104 native compiler tests pass.
|
||||
```
|
||||
|
||||
## Record — `28d19da`
|
||||
|
||||
```
|
||||
strip the compile-time machinery the seam replaces
|
||||
|
||||
PREDICTION: codegen.el drops below 4661, its size before any of these passes.
|
||||
RESULT: FALSE. 5157 -> 5096. Still +435 over baseline.
|
||||
|
||||
injects_at_entry collapsed into the seam removed
|
||||
guards_at_entry collapsed into the seam removed
|
||||
injects_at_exit needs the body-helper wrapper STRUCTURAL
|
||||
wraps_body needs the closure + wrapper structural
|
||||
prohibits_outside a #error cannot be emitted at runtime
|
||||
|
||||
The wrapper is not a consequence of compile-time resolution. Early returns must
|
||||
be routed through something no matter when the target is resolved, so exit
|
||||
injection was never going to collapse. I predicted it would because I had
|
||||
conflated "resolved late" with "emitted less".
|
||||
|
||||
What did collapse is entry injection and refusal -- 61 lines of compiler
|
||||
replaced by one refusable indirection, with the capability now bindable after
|
||||
the binary exists.
|
||||
|
||||
8 tests fail, and they are exactly the 8 controls for compile-time entry
|
||||
injection and guards. No unrelated breakage: the controls reported precisely
|
||||
what moved. They assert emission of something that now happens at runtime, so
|
||||
they need rewriting as integration tests -- which the framework does not
|
||||
currently support, because runtime binding needs a built binary and an
|
||||
environment, not compile_capture.
|
||||
|
||||
Verified after the strip: fixpoint gen2==gen3, observation and refusal both
|
||||
work through the seam with the compiler knowing nothing about either.
|
||||
```
|
||||
|
||||
## Record — `8bbb750`
|
||||
|
||||
```
|
||||
control the claim that cannot be unit tested
|
||||
|
||||
The seam's whole claim is that a construct declared AFTER a binary exists
|
||||
applies to that already-built program. compile_capture only sees emitted text,
|
||||
so it structurally cannot check this: it needs a built binary, a linked target,
|
||||
and an environment. Verified by hand until now, which is the standing problem
|
||||
this session has been about.
|
||||
|
||||
tests/integration/seam_binding.sh builds a probe from El source containing no
|
||||
construct at all, links a target that El never references, and asserts:
|
||||
|
||||
ok unbound program is unaffected
|
||||
ok a construct declared AFTER the build applies
|
||||
ok a construct declared after the build can REFUSE
|
||||
ok an unlinked target is skipped, not fatal
|
||||
ok a binding for a different fn does not fire
|
||||
ok two constructs compose on one crossing
|
||||
|
||||
6 assertions, 6 passed, 0 failed
|
||||
|
||||
The eight controls that failed after the strip were replaced, not repaired.
|
||||
They asserted compile-time emission of capability that moved to runtime;
|
||||
contorting them would have kept an assertion whose subject no longer exists.
|
||||
Three took their place, asserting the emitted shape, and the behaviour they
|
||||
used to cover is now the integration harness's job -- which is the honest
|
||||
division, since the shape and the behaviour are no longer the same fact.
|
||||
|
||||
99/99 native compiler tests pass. Fixpoint holds.
|
||||
```
|
||||
|
||||
## Record — `24f7fb5`
|
||||
|
||||
```
|
||||
land the runtime seam: resolve the crossing at execution
|
||||
|
||||
Five compile-time passes added 491 lines to the thing that was supposed to stop
|
||||
growing. The seam is ~55 lines of C and one line of emission, and it does at
|
||||
runtime what three of those five kinds did at compile time -- for programs that
|
||||
are already built.
|
||||
|
||||
a construct declared AFTER the binary exists applies to it
|
||||
free when unused: 0.36s vs 0.37s baseline across 267 indirections
|
||||
dlsym was the cost, not the table scan; resolve-once recovered 3.5x
|
||||
refusal works, composition works, unlinked targets are skipped not fatal
|
||||
|
||||
injects_at_exit and wraps_body do NOT collapse: early returns must route
|
||||
through the body-helper wrapper regardless of when the target is resolved. The
|
||||
wrapper is structural, which I had wrong. prohibits_outside cannot move at all
|
||||
-- a #error has no runtime.
|
||||
|
||||
Controls: 99/99 native compiler tests, plus tests/integration/seam_binding.sh
|
||||
(6/6) for the claim compile_capture structurally cannot see.
|
||||
```
|
||||
@@ -0,0 +1,45 @@
|
||||
# invocation is not composable
|
||||
|
||||
One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
|
||||
commit message as written at the time, before the outcome was known to anyone
|
||||
reading this file.
|
||||
|
||||
## Record — `bc2f26d`
|
||||
|
||||
```
|
||||
EXPERIMENT: invocation control resolves at runtime
|
||||
|
||||
ISHIKAWA: why did wraps_body need compile-time knowledge? Because the wrapper
|
||||
called the target directly. If the wrapper calls through the seam instead, the
|
||||
seam can call the body itself, and a construct bound after the build decides
|
||||
how and whether to invoke it.
|
||||
|
||||
PREDICTIONS AND RESULTS
|
||||
P1 wrap becomes runtime-bindable TRUE body x3 -> 21,
|
||||
never invoked -> 111
|
||||
P2 codegen shrinks TRUE 5042 -> 4977
|
||||
P3 cost 5-10% from an indirect call on every fn TRUE 0.36s -> 0.39s, ~8%
|
||||
P4 zero-param fns break on the empty struct TRUE empty struct is a GNU
|
||||
extension, empty init
|
||||
is C23. Fixed with a
|
||||
char field.
|
||||
P5 fixpoint holds TRUE
|
||||
|
||||
PROCESS FAILURE worth recording: my first patch silently did not apply because
|
||||
I dropped the assert on the string replacement. The build then failed with
|
||||
"undeclared identifier __thunk_noargs", which I nearly attributed to the
|
||||
empty-struct prediction. The guard that would have caught it existed and I
|
||||
removed it -- the same shape as every other defect found tonight.
|
||||
|
||||
Removed: declare_wrap, decorator_wrap, cg_wrap_target, cg_wrap_construct,
|
||||
params_to_call_args, and the wraps_body scanner branch.
|
||||
|
||||
prohibits_outside is now the ONLY construct kind left at compile time, and it
|
||||
cannot move: a #error has no runtime.
|
||||
```
|
||||
|
||||
## Record — `c04d68f`
|
||||
|
||||
```
|
||||
land runtime invocation control: only prohibition remains compiled
|
||||
```
|
||||
@@ -0,0 +1,53 @@
|
||||
# the emitter adjudicates
|
||||
|
||||
One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
|
||||
commit message as written at the time, before the outcome was known to anyone
|
||||
reading this file.
|
||||
|
||||
## Record — `c741cfe`
|
||||
|
||||
```
|
||||
EXPERIMENT: prohibition becomes a query over emitted relations
|
||||
|
||||
I said prohibition could not move because "a #error has no runtime". That
|
||||
conflated two separable things: WHEN a violation is detected (build time --
|
||||
correct, and unchanged) and WHERE the rule and the checker live (the compiler
|
||||
-- assumed).
|
||||
|
||||
A prohibition is a containment relation over the call graph. So codegen now
|
||||
records what it saw:
|
||||
|
||||
sneaky calls raw_sql
|
||||
allowed calls raw_sql
|
||||
allowed calls @repository
|
||||
repository calls prohibits:raw_sql
|
||||
|
||||
and tools/check/prohibitions.sh decides, at build time, outside the compiler.
|
||||
|
||||
PREDICTIONS AND RESULTS
|
||||
P1 codegen can emit the call graph it already walks TRUE
|
||||
P2 the check becomes a query outside the compiler TRUE
|
||||
P3 all prohibition decisions leave codegen TRUE zero #errors now
|
||||
P4 violations still caught at build time TRUE exit=1
|
||||
P5 codegen drops below the 4661 baseline FALSE 4962, +301
|
||||
|
||||
P5 is the finding. The TRAVERSAL is irreducible -- you must walk the AST to
|
||||
find calls, and those ~120 lines do not move no matter who decides. What is not
|
||||
irreducible is the rule (which names) or the decision (#error). Those left. I
|
||||
predicted the whole 223 lines would go because I had not separated walking from
|
||||
adjudicating.
|
||||
|
||||
Still compiled, and measured rather than assumed: the capability-tier system
|
||||
(cap_check_call, is_self_formation_call, is_dharma_call, is_llm_call,
|
||||
cap_record_violation, emit_cap_violations) is 76 lines of the same shape --
|
||||
prohibits_WITHIN rather than prohibits_outside, so the checker needs the
|
||||
opposite polarity to absorb it.
|
||||
|
||||
98/98 native, 4/4 prohibition_query.sh, 7/7 seam_binding.sh, fixpoint ok.
|
||||
```
|
||||
|
||||
## Record — `60c07ad`
|
||||
|
||||
```
|
||||
land prohibition-as-query: the emitter records, it no longer adjudicates
|
||||
```
|
||||
@@ -0,0 +1,49 @@
|
||||
# policy inside the compiler
|
||||
|
||||
One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
|
||||
commit message as written at the time, before the outcome was known to anyone
|
||||
reading this file.
|
||||
|
||||
## Record — `c2d9596`
|
||||
|
||||
```
|
||||
EXPERIMENT: the capability tier becomes shipped policy plus a query
|
||||
|
||||
Capability differs from prohibits_outside in one way that matters: a utility
|
||||
program cannot be trusted to declare its own restrictions, because it would
|
||||
declare none. So the policy comes from OUTSIDE the program -- it ships with the
|
||||
language as data, editable without a compiler release.
|
||||
|
||||
tools/check/capabilities.rel 18 names that were string literals in codegen
|
||||
tools/check/capabilities.sh the query that decides
|
||||
|
||||
PREDICTIONS AND RESULTS
|
||||
P1 codegen emits kind + call graph, drops the 4 name tests TRUE zero #errors
|
||||
P2 the 18 literals become a data file TRUE
|
||||
P3 the checker catches capability violations TRUE exit=1
|
||||
P4 codegen drops ~76 lines TRUE 4963 -> 4881
|
||||
P5 below the 4661 baseline FALSE ~+230
|
||||
|
||||
TWO DEFECTS THE HARNESS FOUND THAT READING WOULD NOT HAVE
|
||||
|
||||
1. Calls inside main became invisible. cg_fn returns early for main -- C
|
||||
provides its own -- so hooking the recording there left every call in main
|
||||
unrecorded: a blind spot exactly where a program does its work. The old
|
||||
cap_check_call ran from cg_expr and did see main. Moved the recording to
|
||||
cg_expr.
|
||||
|
||||
2. Caller attribution was stale. __cg_current_fn kept whatever cg_fn set last,
|
||||
so a violation in main was reported against the previously emitted function.
|
||||
The test still PASSED, because the violation was detected -- only the name
|
||||
was wrong, and a diagnostic naming the wrong fn is worse than none. Fixed at
|
||||
all three main-emission sites; the first patch missed two because the live
|
||||
path is codegen_streaming.
|
||||
|
||||
98/98 native, 7/7 + 4/4 + 5/5 integration, fixpoint ok.
|
||||
```
|
||||
|
||||
## Record — `29f78f9`
|
||||
|
||||
```
|
||||
land capability-as-policy: eighteen literals become a data file
|
||||
```
|
||||
@@ -0,0 +1,54 @@
|
||||
# a second copy of the header
|
||||
|
||||
One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
|
||||
commit message as written at the time, before the outcome was known to anyone
|
||||
reading this file.
|
||||
|
||||
## Record — `9cc6040`
|
||||
|
||||
```
|
||||
EXPERIMENT: derive arity from the runtime's own declarations
|
||||
|
||||
codegen.el carried builtin_arity(): 344 lines, 300 entries, a hand-maintained
|
||||
second copy of el_runtime.h.
|
||||
|
||||
PREDICTIONS AND RESULTS
|
||||
P1 the table duplicates the header TRUE 243 shared names
|
||||
P2 they have already drifted FALSE ZERO drift. The
|
||||
duplicate had been
|
||||
maintained correctly.
|
||||
P3 codegen can emit call-arity relations TRUE
|
||||
P4 the check becomes a query against the header TRUE
|
||||
P5 codegen drops to roughly baseline TRUE 4903 -> 4512,
|
||||
149 BELOW the 4661
|
||||
it started at
|
||||
|
||||
P2 being false is the better result: the table was not WRONG, it was
|
||||
INCOMPLETE. 110 functions the runtime declares had no entry, so calling them
|
||||
with the wrong argument count produced no El-level diagnostic at all. Measured:
|
||||
the old compiler reports 0 arity errors for __http_do_map_to_file(1); the query
|
||||
reports "takes 5 arguments, called with 1".
|
||||
|
||||
Deriving from the header fixes coverage AND makes drift impossible by
|
||||
construction. 503 signatures, versus 300 entries maintained by hand.
|
||||
|
||||
THREE DEFECTS IN MY OWN CHECKER, each found by running it rather than reading it
|
||||
1. El names and C names differ -- `println` is `__println`. 60 of 500 decls
|
||||
carry the prefix and codegen owns the mapping; the old table carried both
|
||||
keys. One rule covers all 60.
|
||||
2. Multi-line declarations parsed as zero params, so the checker reported
|
||||
"takes 0" for a function taking 5. A diagnostic with the wrong number in it
|
||||
is worse than none -- the same shape as the stale caller attribution in the
|
||||
previous pass.
|
||||
3. Fixing (2) by joining lines dropped 500 signatures to 334, because a
|
||||
declaration preceded by a comment no longer started its record. Comments
|
||||
are stripped first now.
|
||||
|
||||
98/98 native, 5/5 arity_query.sh, fixpoint ok.
|
||||
```
|
||||
|
||||
## Record — `d9e301b`
|
||||
|
||||
```
|
||||
land arity-from-header: the runtime declares its own surface
|
||||
```
|
||||
@@ -0,0 +1,52 @@
|
||||
# one type erases the return
|
||||
|
||||
One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
|
||||
commit message as written at the time, before the outcome was known to anyone
|
||||
reading this file.
|
||||
|
||||
## Record — `d2d89fc`
|
||||
|
||||
```
|
||||
EXPERIMENT: temporal types as data — and the pass that GREW the compiler
|
||||
|
||||
This block is structurally unlike the previous four. It does not only
|
||||
adjudicate, it DISPATCHES: Instant + Duration must become el_instant_add_dur,
|
||||
LocalDate + Duration must become el_local_date_add_dur. The emitted C depends on
|
||||
the type answer, so it cannot move to a post-hoc query. Selecting which call to
|
||||
emit is an emitter's actual job.
|
||||
|
||||
PREDICTIONS AND RESULTS
|
||||
P1 the block conflates dispatch with adjudication TRUE
|
||||
P2 adjudication can move, dispatch cannot TRUE
|
||||
P3 this pass shrinks codegen far less than the last TRUE, and worse:
|
||||
4513 -> 4537, it GREW
|
||||
by 24 lines
|
||||
P4 the rules are affine algebra, closed by construction TRUE
|
||||
P5 no type propagation -- name tracking plus a
|
||||
hardcoded list of which builtins return which type TRUE, 19 names
|
||||
|
||||
P3 is the honest result and it is not spun: moving 19 names into a data file
|
||||
cost more lines than it saved, because a generic loader is larger than the
|
||||
enumeration it replaces. The win is not line count. It is that adding a 20th
|
||||
temporal builtin is now a one-line edit to signatures.rel instead of a compiler
|
||||
change, and that the data is inspectable.
|
||||
|
||||
WHY THE HEADER CANNOT SUPPLY THIS, unlike arity: el_runtime.h declares every
|
||||
builtin as returning el_val_t, because El has ONE type. That single type is why
|
||||
the whole seam is cheap and it is exactly why the C boundary cannot say that
|
||||
now() returns an Instant while unix_seconds() returns an Int. The El-level type
|
||||
is real and the boundary erases it.
|
||||
|
||||
INCOMPLETE, and stated rather than hidden: P2 said adjudication could move to a
|
||||
query. It has NOT. Violations still emit TIME_TYPE_ERROR inline from the
|
||||
emitter. Only the type DATA moved. Moving the adjudication needs the operand
|
||||
types recorded as relations, which is a further pass.
|
||||
|
||||
98/98 native, 4/4 temporal_signatures.sh, fixpoint ok.
|
||||
```
|
||||
|
||||
## Record — `e01e079`
|
||||
|
||||
```
|
||||
land temporal signatures as data: the type table leaves, the dispatch stays
|
||||
```
|
||||
@@ -0,0 +1,47 @@
|
||||
# judgment lives with knowledge
|
||||
|
||||
One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
|
||||
commit message as written at the time, before the outcome was known to anyone
|
||||
reading this file.
|
||||
|
||||
## Record — `e8e25a0`
|
||||
|
||||
```
|
||||
EXPERIMENT: temporal adjudication moves out; the placeholder stays
|
||||
|
||||
The previous pass moved the type DATA and left the judgment inline, which I
|
||||
stated rather than hid. This finishes it.
|
||||
|
||||
PREDICTIONS AND RESULTS
|
||||
P1 codegen can emit operand-type relations TRUE
|
||||
"main calls temporal:instant_plus_instant"
|
||||
P2 the affine rules are a small closed set as data TRUE 6 rules
|
||||
P3 violations still caught at build time TRUE exit=1
|
||||
P4 the reporter leaves codegen TRUE 4538 -> 4507
|
||||
P5 the TIME_TYPE_ERROR placeholder must STAY TRUE
|
||||
|
||||
P5 is the boundary of this whole approach. The emitter has to emit SOMETHING
|
||||
for an illegal expression -- it cannot emit nothing and it cannot decide what
|
||||
the program meant. So the placeholder is irreducible in the same way the AST
|
||||
traversal was: what moved is the judgment and the wording, not the fact that
|
||||
something must be written.
|
||||
|
||||
The rules are affine algebra and the set is closed because there are only two
|
||||
kinds of thing. An Instant is a POINT, a Duration is a DISPLACEMENT: add a
|
||||
displacement to a point, subtract two points for a displacement, combine
|
||||
displacements. Nothing else is meaningful, which is why the enumeration in
|
||||
temporal.rel cannot grow the way an allowlist does.
|
||||
|
||||
A defect in my own checker, found by running it: the .rel file uses aligned
|
||||
columns and my awk assumed a single space, so the message came out with the
|
||||
rule key still prefixed. Same class as the multi-line header parse in the arity
|
||||
pass -- formatting assumptions that only fail when you look at the output.
|
||||
|
||||
98/98 native, 6/6 temporal_query.sh, fixpoint ok.
|
||||
```
|
||||
|
||||
## Record — `50425f3`
|
||||
|
||||
```
|
||||
land temporal adjudication as a query: the emitter records, the rules are data
|
||||
```
|
||||
@@ -0,0 +1,49 @@
|
||||
# thirty five return types
|
||||
|
||||
One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
|
||||
commit message as written at the time, before the outcome was known to anyone
|
||||
reading this file.
|
||||
|
||||
## Record — `cbef1c1`
|
||||
|
||||
```
|
||||
EXPERIMENT: Int return types as data — and the bug that fell out
|
||||
|
||||
PREDICTIONS AND RESULTS
|
||||
P1 is_int_call's 35 hardcoded names move to data TRUE
|
||||
P2 is_int_name stays -- it is annotation propagation TRUE
|
||||
P3 the dispatch stays -- it is emission TRUE
|
||||
P4 codegen shrinks ~40 lines TRUE 4507 -> 4469
|
||||
P5 the design doc's characterisation is WRONG TRUE
|
||||
P6 the moved data also fixes the bug it exposed TRUE
|
||||
|
||||
P5 CORRECTS THE RECORD. el-language-design.md and geometry-vs-code.md both cite
|
||||
"== lowering to str_eq unless both operand names are in a hardcoded int-name
|
||||
set -- a literal list of variable names treated as integers" as the paradigm
|
||||
defect. It is not one. __int_names is populated from TYPE ANNOTATIONS
|
||||
(param["type"] == "Int"), which is primitive but legitimate type propagation.
|
||||
The actual defect was is_int_call: 35 hardcoded builtin return types, the same
|
||||
shape as the temporal 19.
|
||||
|
||||
P6 IS A LIVE CORRECTNESS BUG, PRE-EXISTING, NOW FIXED
|
||||
|
||||
let a = str_len("hello") // no annotation
|
||||
let b = str_len("hi")
|
||||
let c = a + b // -> el_str_concat(a, b) on two integers
|
||||
|
||||
Verified identical on the pre-change compiler, so not a regression. It compiled
|
||||
clean, ran, and printed NOTHING where it should print 7. No error at any layer.
|
||||
|
||||
The repair is three lines: an unannotated let takes its type from what the
|
||||
initialiser returns. The return types were already required for dispatch and
|
||||
were simply never consulted at the binding site. Moving them into data is what
|
||||
made the gap visible -- reading the code for eight hours did not.
|
||||
|
||||
98/98 native + 2 new, 31/31 integration, fixpoint ok.
|
||||
```
|
||||
|
||||
## Record — `505e5e7`
|
||||
|
||||
```
|
||||
land int signatures, and repair a silent miscompilation they exposed
|
||||
```
|
||||
@@ -0,0 +1,57 @@
|
||||
# keywords that reserve nothing
|
||||
|
||||
One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
|
||||
commit message as written at the time, before the outcome was known to anyone
|
||||
reading this file.
|
||||
|
||||
## Record — `0143cc4`
|
||||
|
||||
```
|
||||
ANSWER: is a grammar a convention, or a region?
|
||||
|
||||
Both, at different layers -- and it is the same split as serialization: the
|
||||
convention is the BASIS, never the ACT.
|
||||
|
||||
lexeme -> token `fn` means function-start because someone said so CONVENTION
|
||||
shape recognition given tokens, which construct is this REGION
|
||||
source -> structure parsing is transduction onto that basis GEOMETRY
|
||||
byte traversal something must read them in order IRREDUCIBLE
|
||||
|
||||
Three things push the ACT toward region rather than convention: ambiguity
|
||||
(a * b needs context; a grammar resolves it with the lexer hack, a region by
|
||||
neighbourhood), error recovery (nearest-region is free), and precedence, which
|
||||
is ordering along an axis with a conventional parameter.
|
||||
|
||||
AND THE SHOULD GATE SAYS NO TO THE OBVIOUS MOVE
|
||||
|
||||
Every other table this session moved to data. This one stays code. The keyword
|
||||
set is CLOSED by the language definition -- it does not leak the way an
|
||||
allowlist does -- and the lexer runs before the program is understood, so a
|
||||
program can never declare its own keywords. Externalising it costs file I/O on
|
||||
every compile and buys nothing. Same verdict as is_digit in ASCII.
|
||||
|
||||
WHAT WAS ACTUALLY WRONG: five of 46 keywords were consumed by no parser or
|
||||
codegen path. sealed, activate, seed, protocol, impl. Each stole an identifier
|
||||
from users for nothing.
|
||||
|
||||
SECOND SILENT MISCOMPILATION OF THE DAY. Using one did not fail to parse:
|
||||
|
||||
let seed = 42
|
||||
let impl = seed + 1
|
||||
|
||||
compiled CLEAN -- zero cc errors -- and printed 0 instead of 44. No diagnostic
|
||||
at any layer. Fixed by removing the five.
|
||||
|
||||
A DEFECT IN MY OWN MEASUREMENT, caught before it did damage: my first pass
|
||||
checked only parser.el and reported `test` as inert too. codegen consumes it at
|
||||
4135 for --test mode, and the tree has 408 uses. Removing it would have broken
|
||||
every test in the suite. The measurement was re-run across all four consumers.
|
||||
|
||||
100/100 native + 2 new, 31/31 integration, fixpoint ok.
|
||||
```
|
||||
|
||||
## Record — `067dd40`
|
||||
|
||||
```
|
||||
answer the parsing question: a grammar is a basis, and five keywords reserved nothing
|
||||
```
|
||||
@@ -0,0 +1,53 @@
|
||||
# no namespacing at all
|
||||
|
||||
One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
|
||||
commit message as written at the time, before the outcome was known to anyone
|
||||
reading this file.
|
||||
|
||||
## Record — `79f6cb7`
|
||||
|
||||
```
|
||||
ANSWER: if the partition is a neighbourhood, does linking survive?
|
||||
|
||||
The question is premature, and measuring says why. El's partition is a
|
||||
FILESYSTEM PATH, not a neighbourhood, and there is no namespacing at all.
|
||||
|
||||
MEASURED
|
||||
import is textual inlining (resolve_imports), guarded against double
|
||||
inclusion by a __elc_imp__:<path> state key
|
||||
when a .elh header exists the header is inlined instead and the .el is marked
|
||||
seen, so symbols resolve at C link time -- so linking IS real, delegated to C
|
||||
two modules defining `helper` emit two C functions into one translation unit
|
||||
|
||||
So linking barely survives the PATH partition. Whether it survives a
|
||||
neighbourhood partition cannot be asked yet.
|
||||
|
||||
A DIAGNOSTIC REGRESSION I CAUSED, found by asking this question. cc does catch
|
||||
the collision, but reports:
|
||||
|
||||
error: redefinition of '__el_body_helper'
|
||||
error: redefinition of '__env_helper'
|
||||
error: redefinition of '__thunk_helper'
|
||||
error: redefinition of 'helper'
|
||||
|
||||
The user's own function is FOURTH. The first three are generated symbols
|
||||
introduced by the unconditional-wrapper pass earlier today -- before it, there
|
||||
was one clear message. Repaired by catching the collision at El level instead:
|
||||
|
||||
duplicate definition: 'helper' is defined 2 times — El has no namespacing,
|
||||
so imported modules share one global scope
|
||||
|
||||
LIMIT, stated rather than hidden: textual inlining destroys file provenance. By
|
||||
the time codegen runs there is one source string, so the message can say WHICH
|
||||
name collides but not which files. Naming a.el and b.el needs provenance
|
||||
threaded through resolve_imports.
|
||||
|
||||
104/104 native, 4/4 definitions_query.sh, the compiler itself reports clean,
|
||||
fixpoint ok.
|
||||
```
|
||||
|
||||
## Record — `f23cb2b`
|
||||
|
||||
```
|
||||
answer the module question: the partition is a path, and there is no namespacing
|
||||
```
|
||||
@@ -0,0 +1,64 @@
|
||||
# tokens carry no position
|
||||
|
||||
One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
|
||||
commit message as written at the time, before the outcome was known to anyone
|
||||
reading this file.
|
||||
|
||||
## Record — `6c975b1`
|
||||
|
||||
```
|
||||
thread provenance through resolve_imports
|
||||
|
||||
The module question ended with a limit: textual inlining destroys file
|
||||
provenance, so a duplicate-definition message could name the symbol but not the
|
||||
files. Threading it exposed a bigger absence first.
|
||||
|
||||
TOKENS HAD NO POSITION AT ALL. A token was a flat (kind, value) pair, so NO
|
||||
diagnostic in El could name a place -- every error named a symbol and never a
|
||||
line. That is the prerequisite the module question was resting on.
|
||||
|
||||
THE CHAIN, end to end
|
||||
lexer counts newlines; tok_append mints (kind, value, line)
|
||||
parser stride 2 -> 3; tok_line added; FnDef carries its line
|
||||
codegen records <fn> defines_at:<line>
|
||||
resolve_imports publishes <file> spans <start> <end> for the combined source
|
||||
checker maps a combined line back to file:line-within-that-file
|
||||
|
||||
duplicate definition: 'helper' is defined 2 times — El has no namespacing,
|
||||
so imported modules share one global scope
|
||||
/tmp/modtest/a.el:1
|
||||
/tmp/modtest/b.el:1
|
||||
|
||||
PREDICTIONS AND RESULTS
|
||||
P1 15 stride sites, encapsulated in tok_kind/tok_value TRUE, but see below
|
||||
P2 adding a line field is mechanical TRUE
|
||||
P3 the lexer must count newlines TRUE
|
||||
P4 resolve_imports can record per-file line ranges TRUE
|
||||
P5 the message can then name both files TRUE
|
||||
P6 token memory grows TRUE, 25.0 -> 33.9 MB (+36%)
|
||||
|
||||
FOUR DEFECTS, EACH FOUND BY RUNNING AND NOT BY READING
|
||||
|
||||
1. interp_tokens_append_all walks the token list DIRECTLY with its own copy of
|
||||
the stride. Gen1 built fine and gen2 emitted corrupt C, because the
|
||||
compiler's own source uses string interpolation. My search missed it because
|
||||
I grepped for the variable name `tokens`; it is called `dst`/`result`.
|
||||
Searching by name instead of by shape -- third time today.
|
||||
2. tok_count in test_compiler.el carried the stride too. I had scoped the search
|
||||
to compiler sources and it had escaped into the tests.
|
||||
3. Nested resolve_imports calls accumulated spans into shared state, so each
|
||||
republished meaningless line ranges under the parent's name. Making the
|
||||
buffer local fixed it; guarding the WRITE did not, which is what I tried
|
||||
first.
|
||||
4. The first working version reported b.el:3 -- the COMBINED line against a
|
||||
filename that has no line 3. A file:line that does not match the file is
|
||||
worse than no line at all.
|
||||
|
||||
105/105 native, 37/37 integration, fixpoint ok, compiler self-checks clean.
|
||||
```
|
||||
|
||||
## Record — `cb7289f`
|
||||
|
||||
```
|
||||
thread provenance end to end: a diagnostic can finally name a place
|
||||
```
|
||||
@@ -0,0 +1,53 @@
|
||||
# annotations are never checked
|
||||
|
||||
**Status: verified on `experiment/annotation-checking`, not merged.**
|
||||
|
||||
## Ishikawa — why does El silently miscompile?
|
||||
|
||||
Three bugs found the same day shared one shape.
|
||||
|
||||
```
|
||||
method type tracked by per-function name sets, fed from annotations
|
||||
machine el_val_t erases everything at the C boundary
|
||||
material no propagation through expressions
|
||||
measurement nothing verifies an annotation against what it annotates
|
||||
─────────────────────────────────────────────────────────────────────────
|
||||
root cause El has type ANNOTATIONS but no type CHECKING. The annotation
|
||||
feeds dispatch and is never itself verified.
|
||||
```
|
||||
|
||||
## Predictions
|
||||
|
||||
```
|
||||
P1 let x: Int = "hello" compiles clean expect TRUE
|
||||
P2 let s: String = 42 compiles clean expect TRUE
|
||||
P3 the annotation drives dispatch, unverified expect TRUE
|
||||
P4 same root cause as all three bugs found today expect TRUE
|
||||
P5 checking literal-vs-annotation catches both expect TRUE
|
||||
P6 zero false positives across the compiler's source expect TRUE
|
||||
```
|
||||
|
||||
## Results — 6/6, and worse than a wrong answer
|
||||
|
||||
```
|
||||
let x: Int = "hello"; x + 1 → 4343631981 a string POINTER used as an integer
|
||||
let s: String = 42; println(s) → nothing address 42 dereferenced as a string
|
||||
```
|
||||
|
||||
The first **leaks a raw memory address into program output**. The second is an
|
||||
**arbitrary-read primitive** if that integer is ever attacker-influenced.
|
||||
|
||||
Verified: 6/6, zero false positives across the compiler's own source, fixpoint
|
||||
ok, 105/105 native.
|
||||
|
||||
## Six Sigma
|
||||
|
||||
The emitter only **records** the mismatch; `tools/check/annotations.sh` decides —
|
||||
consistent with every other check. Literals are checked because they are
|
||||
unambiguous.
|
||||
|
||||
**Incomplete, stated not hidden:** only literals. `let x: Int = some_string_fn()`
|
||||
still passes, because `signatures.rel` carries Int/Instant/Duration and no
|
||||
String entries. That is a data gap, not a capability limit — every El function
|
||||
declares its return type in source and codegen already holds `ret_type` on every
|
||||
`FnDef`.
|
||||
@@ -0,0 +1,88 @@
|
||||
# async — half expressible, and the cycle that was dogma
|
||||
|
||||
**Status: replicated and corroborated. Three runs — the first was invalid.**
|
||||
|
||||
> **Chain of custody note, 2026-08-17.** The original measurements were produced
|
||||
> by a C stub written in `/tmp`, and that artifact was destroyed when the session
|
||||
> worktrees were removed. For a period this file asserted results with nothing
|
||||
> behind them — a claim inside an evidence record, which is the defect that turns
|
||||
> a chain into a pile. It was **rerun**, not reconstructed: reconstructing the
|
||||
> missing file would have been a fabrication with a fresh timestamp.
|
||||
>
|
||||
> The fixture now lives at `lang/tests/integration/fixtures/future.c` and the
|
||||
> harness at `lang/tests/integration/async_future.sh`, so a third party can
|
||||
> reproduce this without taking my word for it. **6/6.**
|
||||
>
|
||||
> The replication is labelled as such: the outcomes were already known when the
|
||||
> harness was written, so its expectations are not predictions committed in
|
||||
> advance. Its value is reproducibility, not foresight.
|
||||
|
||||
## The first attempt was DOGMA, not science
|
||||
|
||||
I had just finished arguing that `@async` was expressible, then ran something to
|
||||
confirm it. **No prediction was committed.** The test was rigged in a way that
|
||||
should have been visible while writing it:
|
||||
|
||||
```c
|
||||
pthread_create(&t,NULL,runner,NULL); pthread_join(t,NULL);
|
||||
```
|
||||
|
||||
`join` immediately after `create` — the caller blocks until the body finishes.
|
||||
That is a thread round-trip, not deferral. And the test printed the word
|
||||
`DEFERRED` itself: I wrote the conclusion into the output and read it back.
|
||||
|
||||
```
|
||||
Ishikawa on the rigged test
|
||||
method ran after concluding, not to decide
|
||||
machine nothing forces a prediction before execution
|
||||
material the assertion was written into the output string
|
||||
measurement no falsification criterion existed, so nothing could fail
|
||||
root cause the test was authored by the party holding the conclusion,
|
||||
with no commitment made before it ran
|
||||
```
|
||||
|
||||
Discarded and re-run properly.
|
||||
|
||||
## Second run — predictions committed first
|
||||
|
||||
```
|
||||
P1 the caller proceeds while the body runs expect TRUE
|
||||
P2 interleaving is observable in timestamps expect TRUE
|
||||
P3 the result cannot be retrieved — one 64-bit slot, no
|
||||
future type, so the wrap either blocks or returns
|
||||
something that is not the result expect TRUE
|
||||
P4 therefore HALF expressible: fire-and-forget yes, await no expect TRUE
|
||||
```
|
||||
|
||||
## Results — 4/4
|
||||
|
||||
```
|
||||
[ 18 us] wrap RETURNS to caller
|
||||
[ 29 us] body START
|
||||
caller continues, got 0
|
||||
[ 50176 us] body END (computed 42)
|
||||
caller done
|
||||
```
|
||||
|
||||
The caller got **0, not 42**. Both of my earlier claims were wrong in opposite
|
||||
directions: "not expressible" was too strong — fire-and-forget works today,
|
||||
bound after the build, no compiler change. "Expressible" was too strong the
|
||||
other way.
|
||||
|
||||
## Follow-on cycle — a future is one more tagged object
|
||||
|
||||
```
|
||||
P1 el_val_t already carries tagged heap objects TRUE 5 magic tags exist
|
||||
P2 a future is one more TRUE
|
||||
P3 the caller awaits and gets 42 TRUE
|
||||
P4 ZERO compiler changes TRUE runtime C + one binding
|
||||
P5 the unbound path still works FALSE SIGSEGV
|
||||
```
|
||||
|
||||
**P4 is the result.** `@async` — called unexpressible for hours — needs no
|
||||
compiler change. A future is one more magic-tagged heap object; `defer` returns
|
||||
the handle, `el_await` blocks.
|
||||
|
||||
**P5 is the failure that mattered.** Sixty seconds after diagnosing
|
||||
`let s: String = 42` as an arbitrary read, I wrote the identical defect into
|
||||
`el_await`: reading `->magic` off an unvalidated slot. That opened cycle 19.
|
||||
@@ -0,0 +1,61 @@
|
||||
# a convention is not a gate
|
||||
|
||||
One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
|
||||
commit message as written at the time, before the outcome was known to anyone
|
||||
reading this file.
|
||||
|
||||
## Record — `9a6c161`
|
||||
|
||||
```
|
||||
a slot must be validated before it is dereferenced
|
||||
|
||||
ISHIKAWA: el_val_t carries integers AND tagged heap pointers, so "is this a
|
||||
pointer" is undecidable without checking first. That check was a CONVENTION
|
||||
every author had to know rather than a GATE they had to pass through, and
|
||||
looks_like_heap_obj was static -- so every sibling translation unit re-derived
|
||||
it.
|
||||
|
||||
MEASURED, across the five existing tags
|
||||
geom_of looks_like_heap_obj full guard correct
|
||||
mfld_of looks_like_heap_obj full guard correct
|
||||
el_bin_lookup (uintptr_t)p < 4096 floor only reads 8 bytes BACKWARD
|
||||
el_input_len s ? ... : 0 NULL only strlen's an integer
|
||||
|
||||
sha256_hex(50000) -> exit 139, SIGSEGV, compiled clean
|
||||
|
||||
PREDICTIONS AND RESULTS
|
||||
P1 looks_like_heap_obj is static, not exported TRUE
|
||||
P2 each tagged type re-derives the check TRUE
|
||||
P3 at least one is missing guard components TRUE (two are)
|
||||
P6 sha256_hex(<int>) reads out of bounds TRUE
|
||||
P8 routing el_bin_lookup through the gate fixes it FALSE
|
||||
P9 the legitimate hash is unchanged TRUE
|
||||
P11 fixpoint and suites hold TRUE
|
||||
|
||||
P8 IS THE USEFUL FAILURE. Guarding the tagged lookup changed nothing --
|
||||
looks_like_heap_obj(49992) correctly returns 0, el_bin_lookup bails, and then
|
||||
el_input_len falls through to strlen() on address 50000. The FALLBACK was the
|
||||
hazard, not the tagged path. A NULL check does not establish that a slot is a
|
||||
pointer. I would have shipped the wrong fix and called it verified.
|
||||
|
||||
A MEASUREMENT DEFECT, fourth today: my first run of the crash reported exit=0,
|
||||
because $? read head's exit through a pipe rather than the program's. I nearly
|
||||
recorded a segfault as a clean run. Same shape as grepping only parser.el and
|
||||
searching by variable name instead of by operation.
|
||||
|
||||
AND I PROVED THE HAZARD FROM THE INSIDE. Sixty seconds after diagnosing
|
||||
`let s: String = 42` as an arbitrary-read primitive, I wrote the identical
|
||||
defect into el_await -- dereferencing ->magic off an unvalidated slot -- and
|
||||
only then found the runtime had already made it twice.
|
||||
|
||||
el_tagged() is now exported in el_runtime.h. Anything that dereferences a slot
|
||||
without passing through it is the defect.
|
||||
|
||||
105/105 native, 42/42 integration across eight harnesses, fixpoint ok.
|
||||
```
|
||||
|
||||
## Record — `3049a70`
|
||||
|
||||
```
|
||||
make the guard a gate: sha256_hex(50000) no longer segfaults
|
||||
```
|
||||
+1
@@ -0,0 +1 @@
|
||||
bash -c cd /Users/will/Development/neuron-technologies/foundation/el/docs/v1/experiments/evidence/cycles && for d in 0*-* 1*-*; do [ -f "$d/MANIFEST.tsv" ] || continue; rows=$(awk -F"\t" "NR>1 && NF>=9 && \$1!=\"sha256\"{c++} END{print c+0}" "$d/MANIFEST.tsv"); stray=$(awk -F"\t" "NR>1 && NF<9{c++} END{print c+0}" "$d/MANIFEST.tsv"); outs=$(ls "$d"/*.out 2>/dev/null | wc -l | tr -d " "); printf "%-46s wellformed_rows=%-4s stray_lines=%-4s out_files=%s\n" "$d" "$rows" "$stray" "$outs"; done
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
00-cross-cycle-codegen-linecounts wellformed_rows=9 stray_lines=9 out_files=10
|
||||
01-constructs-have-nowhere-to-be wellformed_rows=20 stray_lines=6 out_files=20
|
||||
02-a-construct-cannot-refuse wellformed_rows=25 stray_lines=68 out_files=25
|
||||
03-the-wrapper-was-conditional wellformed_rows=39 stray_lines=183 out_files=39
|
||||
04-c-has-no-closure-syntax wellformed_rows=32 stray_lines=26 out_files=32
|
||||
05-the-emitter-discards-what-it-knows wellformed_rows=21 stray_lines=17 out_files=21
|
||||
06-the-crossing-resolves-at-emission wellformed_rows=41 stray_lines=271 out_files=41
|
||||
07-invocation-is-not-composable wellformed_rows=22 stray_lines=18 out_files=22
|
||||
08-the-emitter-adjudicates wellformed_rows=22 stray_lines=88 out_files=22
|
||||
09-policy-inside-the-compiler wellformed_rows=26 stray_lines=135 out_files=26
|
||||
10-a-second-copy-of-the-header wellformed_rows=15 stray_lines=33 out_files=15
|
||||
11-one-type-erases-the-return wellformed_rows=11 stray_lines=0 out_files=11
|
||||
12-judgment-lives-with-knowledge wellformed_rows=10 stray_lines=0 out_files=10
|
||||
13-thirty-five-return-types wellformed_rows=20 stray_lines=0 out_files=20
|
||||
14-keywords-that-reserve-nothing wellformed_rows=15 stray_lines=0 out_files=15
|
||||
15-no-namespacing-at-all wellformed_rows=17 stray_lines=0 out_files=17
|
||||
16-tokens-carry-no-position wellformed_rows=13 stray_lines=0 out_files=13
|
||||
17-annotations-are-never-checked wellformed_rows=1 stray_lines=0 out_files=2
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
commit 9540f2399120172b92e986e081877ff058adbdd3
|
||||
tree clean
|
||||
captured_utc 2026-08-17T17:40:38Z
|
||||
exit 0
|
||||
ms 145
|
||||
sha256_out 8b82c6f04c641f9777dd1bd1f2ddd5dd7c61b502bb9aa33d9a013eaa25137873
|
||||
sha256_err e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
+1
@@ -0,0 +1 @@
|
||||
0
|
||||
+1
@@ -0,0 +1 @@
|
||||
bash tools/evidence/verify-manifest.sh docs/v1/experiments/evidence/cycles
|
||||
+1
@@ -0,0 +1 @@
|
||||
evidence: 0 artifacts verified, 0 altered, 0 missing
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
commit 9540f2399120172b92e986e081877ff058adbdd3
|
||||
tree clean
|
||||
captured_utc 2026-08-17T17:40:38Z
|
||||
exit 0
|
||||
ms 9
|
||||
sha256_out 965c3dc538c178d5a93adc06ac162d01ab3c5c1f21e34ec16673a5669867c4b8
|
||||
sha256_err e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
+1
@@ -0,0 +1 @@
|
||||
0
|
||||
+1
@@ -0,0 +1 @@
|
||||
bash /Users/will/Development/neuron-technologies/foundation/el/tools/evidence/verify-manifest.sh /Users/will/Development/neuron-technologies/foundation/el/docs/v1/experiments/evidence/cycles
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
DIRTY-TREE 11-one-type-erases-the-return/0001-codegen-lines-P3.out (commit fbb3a52220e1) — not reproducible by checkout
|
||||
DIRTY-TREE 11-one-type-erases-the-return/0002-codegen-lines-newline-check.out (commit a116710bacba) — not reproducible by checkout
|
||||
DIRTY-TREE 11-one-type-erases-the-return/0003-signatures-rel-name-count-P5.out (commit a116710bacba) — not reproducible by checkout
|
||||
DIRTY-TREE 12-judgment-lives-with-knowledge/0001-codegen-lines-P4.out (commit a116710bacba) — not reproducible by checkout
|
||||
DIRTY-TREE 12-judgment-lives-with-knowledge/0002-temporal-rel-rule-count-P2.out (commit a116710bacba) — not reproducible by checkout
|
||||
DIRTY-TREE 13-thirty-five-return-types/0001-codegen-lines-P4.out (commit a116710bacba) — not reproducible by checkout
|
||||
DIRTY-TREE 13-thirty-five-return-types/0002-is-int-call-name-count-P1.out (commit a116710bacba) — not reproducible by checkout
|
||||
DIRTY-TREE 16-tokens-carry-no-position/0002-P1-stride-sites-touched.out (commit 99b12f85c6ba) — not reproducible by checkout
|
||||
evidence: 365 artifacts verified, 0 altered, 0 missing
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
commit 9540f2399120172b92e986e081877ff058adbdd3
|
||||
tree clean
|
||||
captured_utc 2026-08-17T17:40:50Z
|
||||
exit 0
|
||||
ms 3949
|
||||
sha256_out cd8adcbc95c1db4fa7848f51a15580de6460b5d5010ee780e4c4aa60f20d2984
|
||||
sha256_err e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
+1
@@ -0,0 +1 @@
|
||||
0
|
||||
+1
@@ -0,0 +1 @@
|
||||
bash -c D=$(mktemp -d); bash /Users/will/Development/neuron-technologies/foundation/el/tools/evidence/verify-manifest.sh "$D"; echo "exit=$? on a directory containing NO manifests at all"; rmdir "$D"
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
evidence: 0 artifacts verified, 0 altered, 0 missing
|
||||
exit=0 on a directory containing NO manifests at all
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
commit 9540f2399120172b92e986e081877ff058adbdd3
|
||||
tree clean
|
||||
captured_utc 2026-08-17T17:41:07Z
|
||||
exit 0
|
||||
ms 19
|
||||
sha256_out 824b7a3f9cfba4b9edb8250714efb5f671b94e15f51abe9e04e7d24e44a19fb6
|
||||
sha256_err e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
+1
@@ -0,0 +1 @@
|
||||
0
|
||||
+1
@@ -0,0 +1 @@
|
||||
bash -c printf "%-11s %-22s %-22s %s\n" CYCLE CLAIMED OBSERVED "OFFSET(parent/commit)"; printf "%-11s %-22s %-22s %s\n" "03/285166c" "5094 -> 5044 (d50)" "5095 -> 5043 (d52)" "-1 / +1"; printf "%-11s %-22s %-22s %s\n" "06/28d19da" "5157 -> 5096 (d61)" "5156 -> 5095 (d61)" "+1 / +1"; printf "%-11s %-22s %-22s %s\n" "07/bc2f26d" "5042 -> 4977 (d65)" "5043 -> 4976 (d67)" "-1 / +1"; printf "%-11s %-22s %-22s %s\n" "08/c741cfe" "4962 (+301)" "4962 (+301)" " 0 / 0"; printf "%-11s %-22s %-22s %s\n" "09/c2d9596" "4963 -> 4881 (d82)" "4962 -> 4896 (d66)" "-1 / -15"; printf "%-11s %-22s %-22s %s\n" "10/9cc6040" "4903 -> 4512 (d391)" "4896 -> 4512 (d384)" "+7 / 0"; echo; echo "Offsets are NOT in a consistent direction. A single counting convention (missing trailing newline, editor last-line number) would produce a uniform offset. It does not."
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
CYCLE CLAIMED OBSERVED OFFSET(parent/commit)
|
||||
03/285166c 5094 -> 5044 (d50) 5095 -> 5043 (d52) -1 / +1
|
||||
06/28d19da 5157 -> 5096 (d61) 5156 -> 5095 (d61) +1 / +1
|
||||
07/bc2f26d 5042 -> 4977 (d65) 5043 -> 4976 (d67) -1 / +1
|
||||
08/c741cfe 4962 (+301) 4962 (+301) 0 / 0
|
||||
09/c2d9596 4963 -> 4881 (d82) 4962 -> 4896 (d66) -1 / -15
|
||||
10/9cc6040 4903 -> 4512 (d391) 4896 -> 4512 (d384) +7 / 0
|
||||
|
||||
Offsets are NOT in a consistent direction. A single counting convention (missing trailing newline, editor last-line number) would produce a uniform offset. It does not.
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
commit 9540f2399120172b92e986e081877ff058adbdd3
|
||||
tree clean
|
||||
captured_utc 2026-08-17T17:46:23Z
|
||||
exit 0
|
||||
ms 8
|
||||
sha256_out df3922caf56164ed2e7e7e69bc9d7926e7decb4366ef8ef870191e86a6098e66
|
||||
sha256_err e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
+1
@@ -0,0 +1 @@
|
||||
0
|
||||
+1
@@ -0,0 +1 @@
|
||||
bash -c for c in 45325f7 addd5120 409bf573 dcaa77d; do n=$(git show "${c}:lang/el-compiler/src/codegen.el" </dev/null 2>/dev/null | wc -l | tr -d " "); printf "%-10s codegen.el=%-6s touched_codegen=%s %s\n" "$c" "$n" "$(git show --name-only --format="" "$c" | grep -c "el-compiler/src/codegen.el")" "$(git log -1 --format="%ci %s" "$c")"; done
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
45325f7 codegen.el=4661 touched_codegen=1 2026-08-16 16:08:40 -0500 singleton: guard the state, not the program's name
|
||||
addd5120 codegen.el=4661 touched_codegen=0 2026-08-16 19:59:43 -0500 runtime: extract engram_text.c, and repair 10 harnesses that could not link
|
||||
409bf573 codegen.el=4661 touched_codegen=0 2026-08-17 04:34:32 -0500 track the architecture docs
|
||||
dcaa77d codegen.el=4670 touched_codegen=1 2026-08-17 04:53:40 -0500 make boundary crossings attributable to the construct that caused them
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user