capabilities.md cited '== lowering to str_eq unless both operand names are in a hardcoded int-name set' as the paradigm defect. That is wrong: __int_names comes from type annotations, which is legitimate propagation. The real defect was 35 hardcoded builtin return types one layer down, and mislocating it hid a live miscompilation of unannotated lets. geometry-vs-code.md listed concurrency and error handling as open. Both are answered: ordering is a partial order and coordination is the price of forgetting; standing is signed, so not-known and known-false are opposite directions rather than one boolean. Added the fourth proof form (adversarial exactness) and recorded that form 1 no longer survives as a verdict -- every row it justified was a basis, not a capability. Also marked cross-cutting concerns as implemented rather than predicted.
8.0 KiB
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 | First read |
|---|---|---|---|
| 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 | write a value as bytes someone else will read | convention — the format was agreed |
| 21 | Text encoding | what bytes mean which characters | convention — UTF-8, ASCII, case tables |
| 22 | Storage | keep a thing past this moment | durability against a device that loses power |
| 23 | Network | send a thing to another machine | wire protocol + socket |
| 24 | Process | start, stop, signal, exit | the OS boundary |
| 25 | Concurrency | more than one thing at once | hardware and OS scheduling |
| 26 | Memory | hold representations while they are in use | the substrate that holds positions |
| 27 | Secrecy | prove authorship; hide content; verify integrity | structurally excluded — see below |
| 28 | Emission | write the surface out as bytes | the physical boundary |
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:
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.