The Math That Didn't Pay Rent

ley-line-open tested whether cellular sheaves could make cache invalidation smarter than a hash check. A four-rung falsification ladder said no — and showed what does earn its keep instead.

· 9 min read

ley-line-open content-addressing experimentation agents

the map · part 7 of 8

ley-line · part 2 of 2


Last time I described the store: content-addressed, hash-chained, the layer that turns “is this genuine” into arithmetic. What I skipped over is a piece that sits just above it — the part that decides whether a hash actually changed anything worth re-deriving. That piece almost shipped with real mathematical machinery behind it. It didn’t, and the reason it didn’t is a better story than if it had.

A layer with fancier vocabulary than the problem needed

leyline-sheaf is a cache-invalidation crate written in the language of cellular sheaves: stalks assigned to regions of code, a coboundary operator δ⁰ measuring disagreement between adjacent regions, invalidation driven by the δ⁰ cascade. It’s real code, and the docstrings were already candid that it was a “heuristic proxy,” not the genuine cohomology. But the design docs around it treated that cohomology as the moat — the thing that would let the cache skip re-derivation not just on identical bytes, but on bytes that changed without changing anything that mattered.

A read-only audit asked the obvious question first: on every input the crate actually sees, what does δ⁰ reduce to? The stalks are SHA-256 hashes. A cryptographic hash is an avalanche function — change one bit of input and roughly half the output bits flip. Two nearly-identical regions produce two maximally distant hashes; there’s no continuum between “same” and “different,” just those two states. The restriction maps turned out to be a single static coordinate mask on every edge, and the cascade turned out to be a plain single-pass walk. Assembled, δ⁰ on hash stalks is a hash-gated reverse-dependency walk. The sheaf math was real, present in the crate, and off the path that actually decided anything.

That’s not a bug. It’s a gap between honest code comments and an ambitious design doc, and it’s exactly the kind of gap constraint-driven development exists to close: don’t let an opinion about what should be true stand in for a predicate that checks whether it is.

A falsification ladder, not a rewrite

The fix on the table was locality-preserving stalks — hypervectors or SimHash instead of raw hashes — so δ⁰ would measure something closer to semantic distance: an edit whose embedding barely moves gets skipped without re-deriving anything. If it worked, that’s a capability no hash system offers, because a hash can’t express “close but not identical.”

Instead of building it, the plan was four cheap experiments, ordered so the idea could die as early as possible:

  • Rung 0 — confirm the current hash-stalk math really does collapse to the plain BFS. It did.
  • Rung 1 — swap in a locality-preserving stalk and construct one cosmetic edit (rename a variable, reflow whitespace) that should read as unchanged. The byte-trigram version inverted: a rename moved the stalk farther than a real edit, because renaming churns more trigrams than a small structural change does. Ruled out.
  • Rung 2 — the one the whole idea hinged on: does a rename-invariant stalk, built from the AST’s node-kind sequence rather than raw bytes, predict whether a region’s derived facts actually changed?
  • Rung 3 — a safety check, independent of whether 1–2 survived: prove a wrong skip decision degrades to unnecessary re-derivation, never to stale data actually served. It held on its own merits.

Rung 2 is where it died, and the way it died is the interesting part.

Real signal, and a floor it couldn’t clear

The AST-structural stalk passed its first gate: on hand-built fixtures, cosmetic edits landed at distance zero and meaningful edits landed well above it — the discrimination the byte stalk had gotten backward. That earned it the expensive test: replay 1,960 real region-edits from ley-line-open’s own git history, and for each one compare the stalk’s distance against whether the re-derived facts actually changed.

The correlation was real. Fact-changing edits moved the stalk about four times as far, on average, as fact-preserving ones — the first stalk in the ladder that wasn’t actively backwards. But a skip gate doesn’t get graded on correlation; it gets graded on how often it skips something it shouldn’t. At the smallest usable threshold, it skipped 60% of the safe cases at the cost of a 10% false-negative rate — serving stale facts one time in ten. Pushing the threshold down never reached zero, because 19 of the edits in the corpus were structurally invisible by construction: a pure callee swap like compute_weight becoming compute_penalty, no branch added, no shape changed. Both versions parse to the identical node-kind sequence. A representation built to ignore identifiers can’t see a change that lives entirely in an identifier. That gives the false-negative rate an irreducible floor around 1.7%, regardless of where the threshold sits.

The number that actually closed the question, though, wasn’t the false-negative rate. It was checking what the embedding added on top of the hash gate that was already running. The hash is already whitespace-insensitive, so it skips cosmetic edits for free — the embedding adds nothing there. Its only possible contribution is on edits where the hash changes but the underlying facts don’t, and that’s precisely the class the embedding can’t safely judge, because the signal it would need — the identifier text — is what it was built to exclude. Trust the embedding’s skip without rechecking the hash, and roughly one skip in ten serves something stale. Recheck the hash afterward, and you’ve paid for the embedding and gained nothing. Either way the marginal value over the hash gate alone is nil or negative. Four small experiments, a couple of days of work, and a definitive no instead of a cohomology-shaped rewrite riding on a hunch.

What the ladder didn’t kill

Two days after the no-go, the same question — does anything beyond a plain hash earn its place in this cache — came back with a different mechanism and a different answer.

A content hash answers “is this stored object identical.” It can’t answer “is this expensive derived view — a call-graph resolution, a lint pass — still valid,” because the view usually depends on a slice of the substrate, sometimes spanning several objects, not on any single object’s hash. The fix wasn’t an approximate distance at all: hash the exact rows the view actually reads — its input closure — and treat an unchanged closure hash as proof the view’s output hasn’t changed. No threshold, no embedding, no statistics. If the closure is provably the same, the output is provably the same, because the view is a deterministic function of it.

On nine hand-built fixtures, that construction skipped every case it was safe to skip and none it wasn’t — five for five, against a whole-object hash that caught none of the safe skips and a structural-embedding variant (the direct descendant of the failed Rung-2 idea) that false-skipped all four of the cases that should have re-run. The strongest fixture renamed a function in a different file from the one being reviewed: the file under review was byte-identical, so a whole-object hash would call it unchanged, but the called function’s definition had moved, and the review’s own answer should change with it. The restriction hash caught it, because the input closure it hashes reaches across the file boundary into exactly the rows the review depends on. At scale the gap widens fast — thousands of rows compared shrink to single digits, and the reported win passing tens of thousands of definitions runs close to twenty times faster.

The write-up settled on a line worth keeping around: restriction maps earned rent. Cohomology did not. The topology — which rows a derived view actually depends on — is doing real work. The coboundary operator that gave the crate its name never was.

Update (2026-07-28). It shipped, and where it shipped is the part I did not see coming. restriction_cache lives in rs/ll-open/sheaf/ — inside the crate named after the mathematics that failed. Two review families ride on it, each with its own restriction: a call-target review over the reference rows, and a public-API review over the definition rows. Because the restrictions differ, renaming a private helper invalidates the first and leaves the second standing, which is the whole point of keying on a closure rather than an object. Both key on the merkle-AST node hash, so the identity survives a reflow or a body edit that changes nothing structural.

The ADR recording the GO is careful in a way worth copying. It links the earlier audit — the one that found the coboundary operator was a hash-gated walk — and states that the finding still holds, and that this positive result does not revive the cohomology. A project that had every incentive to quietly let the win launder the loss instead wrote down that they remain separate.

One correction against my own filing: the ADR’s own header still reads Proposed, while the changelog records it as GO and the module is in the tree. Status drifted in the document, not in the code — which is the same class of defect as a problem doc describing a bug that was fixed months earlier, and I have now been caught by that twice in the same repository.

The shape of the win

Nothing here argues against reaching for unfamiliar math. The sheaf vocabulary is what pointed at restriction maps in the first place — a plainer starting point might never have surfaced “cache on the input closure, not the object” as a candidate at all. What the ladder did was refuse to let the vocabulary’s sophistication stand in for evidence that the specific mechanism it suggested — distance between embeddings — actually predicted anything worth trusting. It didn’t. A much plainer construction, sitting one layer down in the same vocabulary, did.

That’s the same trade the map keeps making at every layer: a hash you can check beats a hunch you’d have to trust, even when the hunch is dressed in real mathematics. The ladder cost a few days. The alternative was shipping a rewrite because the abstraction sounded like it should work.

ley-line-open is open source: github.com/agentic-research/ley-line-open, AGPL-3.0. The full ladder, the replay numbers, and the restriction-addressed follow-up are in the repo’s docs/adr/ and docs/research/.