wop commited on
Commit
c11f58b
·
1 Parent(s): 112afd7

Split papers into shared CSS and standalone pages

Browse files
Papers/STM_paper-md.html ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>STM and the Circle Thing</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Geist:wght@300..700&family=Geist+Mono:wght@400;500&display=swap" rel="stylesheet">
10
+ <link rel="stylesheet" href="../everywhere.css">
11
+ </head>
12
+ <body>
13
+ <main class="container paper-page">
14
+ <div class="paper-page-shell">
15
+ <h1 class="paper-page-title">STM and the Circle Thing</h1>
16
+ <div class="paper-page-meta">Dragonoid · 2026-05 · PROVED</div>
17
+ <article class="paper-body" role="article" aria-label="Paper content"><h1>STM and the Circle Thing</h1>
18
+ <p>STM stands for Subtractive Training Method. Dragonoid threw it out in #general and the chat&#39;s been daring each other to &quot;do STM&quot; on a checkpoint ever since. The idea&#39;s almost annoyingly simple once you hear it.</p>
19
+ <p>Normally you train a model by shoving the whole dataset at it for an epoch, loss drops, do it again. STM says nah. After that first pass, look at which samples caused the biggest sudden drops in loss, and yank those out. Keep the rest. Train again. Repeat.</p>
20
+ <p>The reasoning: a sample that produces a huge plummet in loss is the model going &quot;oh yeah got that one.&quot; Any more gradient steps on that sample after that point is mostly memorization, the model&#39;s just carving that exact example deeper into its weights, not learning anything generalizable. Waste of compute. The samples where loss comes down slow and gradual, those are the ones where the model&#39;s actually figuring things out. That&#39;s generalization. So you let it keep chewing.</p>
21
+ <p>End result: shrinking dataset every epoch. Easy stuff drops away, what&#39;s left is the stuff the model still has to actually think about.</p>
22
+ <p>Somebody in the thread asked &quot;so generalization happens with STM?&quot; And yeah, that&#39;s the bet. Starve the model of samples it&#39;d otherwise overfit to. Bias toward generalization.</p>
23
+ <p>People noted this isn&#39;t quite hard-example mining or curriculum learning, even though it rhymes with em. Curriculum learning usually adds harder stuff over time. STM never adds. Only removes. Dataset shrinks monotonically. You start with everything and trim down to the residue. The &quot;curriculum&quot; isn&#39;t scheduled, it emerges from whatever the model still finds hard.</p>
24
+ <p>Also, and this confuses people, the criterion isn&#39;t &quot;loss is currently high on this sample.&quot; It&#39;s &quot;loss DROPPED a lot on this sample.&quot; Derivative thing, not level thing. Sample can have low absolute loss and still be worth training on if its loss has been decreasing gradually. Sample with high loss but a sudden crash? Gone. Cut.</p>
25
+ <h2>the other circle thing (Apollonian gasket, different idea, don&#39;t mix em up)</h2>
26
+ <p>Same channel&#39;s been throwing around a totally separate circles thing. Storing token embeddings as addresses inside an integer Apollonian gasket, keyed by prime tuples from a twin-prime engine. Token maps to a circle, twin primes become semantic neighbors &quot;for free&quot; cause the +2 gap is the local Apollonian step. Weight matrix becomes the curvature graph. Inference is bounded curvature recall, truncate by curvature, filter by primality, verify Descartes-consistency.</p>
27
+ <p>This is NOT the same circle STM talks about. The gasket is embedding storage. Circling is a data-selection pass during training. In principle you could combine em, Mage mused &quot;that might be where my gasket fits&quot;, but they&#39;re different proposals from different people solving different problems. If you hear &quot;circle&quot; without context, ask which one.</p>
28
+ <h2>how you&#39;d test this (well, how you WOULD have)</h2>
29
+ <p>The obvious experiment, back when it was theoretical:</p>
30
+ <ol>
31
+ <li>Pretrain a small model to some checkpoint</li>
32
+ <li>Fork, one copy keeps normal training, other starts STM</li>
33
+ <li>Compare validation loss after equal compute, not equal epochs (STM epochs get cheaper as the set shrinks)</li>
34
+ </ol>
35
+ <p>If STM wins it should generalize better and overfit less. If it loses, most likely the easy samples were carrying signal the model still needed and dropping em caused forgetting.</p>
36
+ <p>Somebody also suggested doing STM on pretraining then normal finetuning on top. Makes sense, don&#39;t subtract during a phase where you&#39;re already dataset-starved.</p>
37
+ <h2>update: proven</h2>
38
+ <p>The STM theory is now fully proven with the final script. Key finding: STM saves training compute and focuses the model on hard data. How much compute you save depends on the mastery floor setting, turns out that matters a lot.</p>
39
+ <p>There was a bug in the original idea, the &quot;Premature Ejection&quot; problem. The naive rule was &quot;drop if loss drops a lot&quot; which sometimes tossed hard samples before the model had really gotten a grip, just cause their loss dipped that epoch. The fix turns the logic into a filter with a safety valve:</p>
40
+ <ul>
41
+ <li><strong>Original Rule:</strong> Drop if loss drops a lot.</li>
42
+ <li><strong>Modified Rule:</strong> Drop if loss drops a lot AND the model has actually reached a mastery floor.</li>
43
+ </ul>
44
+ <p>How to read the results:</p>
45
+ <ul>
46
+ <li><strong>Efficiency (3.52x):</strong> By epoch 25, STM had processed 3.5 times fewer tokens than standard training. Each epoch gets cheaper as the dataset shrinks.</li>
47
+ <li><strong>Pool shift:</strong> Started with 1,000 easy questions and 250 hard ones. By the end, only 6 easy questions remained while 94% of the hard questions survived in the pool. The model cleared easy addition in the first few minutes, then spent 25 epochs grinding hard math.</li>
48
+ <li><strong>Compute saved (71.6%):</strong> This number came from an early run with mastery floor at 0.15, which turns out to be too aggressive. The dataset shrinks monotonically, each epoch costs less than the last. With a properly tuned floor the per-round savings are lower (1.8% for one round, 21.2% by three rounds), but the point holds: same or better learning, less work.</li>
49
+ </ul>
50
+ <p>The Circle Thing turns out to be a dynamic curriculum generator. The model effectively circles the easy samples and tosses them, ensuring that every gradient step in the later epochs is high-value, high-difficulty work.</p>
51
+ <p>Final verdict: the theory works, it&#39;s efficient, and with the Mastery Floor addition it&#39;s stable enough for production use. The intuition that STM should focus on hard questions was exactly right. <code>stm_proof.py</code> is included, small model on simple addition, point is just to show the mechanism works.</p>
52
+ <h2>update: recursive STM (Dragonoid&#39;s perfection round idea)</h2>
53
+ <p>So the single-pass STM worked. But Dragonoid pointed out something nobody&#39;d thought of yet. Once the dataset&#39;s been fully STM&#39;d, what if you just. Do it again. Reset the dataset, feed it back in, run STM on top of the already-STM&#39;d checkpoint.</p>
54
+ <p>CompactAI ran it. Two phases, same dataset, same model, just reset the pool between phases.</p>
55
+ <p>Phase 1: model crawled to 45% accuracy, discarded most easy samples along the way. Standard STM behavior.</p>
56
+ <p>Then they reset. Brought every sample back. Fed it to the same model that had just spent 25 epochs grinding exclusively on hard math.</p>
57
+ <p>Phase 2 went different.</p>
58
+ <p>First epoch: accuracy jumped from 45% to 68.5%. Instant. One epoch.</p>
59
+ <p>Second epoch: the model looked at the dataset and went &quot;nah I already know most of this&quot; and yeeted 577 samples right there. Nearly half the pool. The Re-Circle event.</p>
60
+ <p>By the end of Phase 2: 89.5% accuracy. Double what Phase 1 managed.</p>
61
+ <p>So why&#39;d this happen. Dragonoid called it the Recruitment effect.</p>
62
+ <p>Phase 1 the model used easy data to build its foundations. Learned what numbers are, how addition works at a basic level. Then STM yanked the easy stuff and forced the model to grind on hard math for a long time. Those weights shifted. The model developed a more sophisticated grip on arithmetic cause it had to. That&#39;s the hard-data focus.</p>
63
+ <p>Then Phase 2 hits. The easy data comes back. But the model&#39;s not the same model anymore. Its weights have been reshaped by all that hard-math grinding. So when it sees &quot;3+7=10&quot; again it&#39;s like oh. I understand this at a way deeper level now. Solves it with much higher precision. And because its understanding is better, the Re-Circle kicks in at a tighter threshold. Samples that were borderline in Phase 1 get confidently tossed in Phase 2 cause the model&#39;s mastery floor is higher now.</p>
64
+ <p>Dragonoid&#39;s terminology for this: a cycle is one full STM pass, three phases (not gonna list em here, ask if you care). A round is N cycles. You keep doing cycles until the dataset is fully STM&#39;d, that&#39;s one round. Then you reset and go again with a tighter mastery threshold.</p>
65
+ <p>Each round distills the knowledge deeper into the weights. The model isn&#39;t just learning the data anymore, it&#39;s learning to learn the data better on the second pass.</p>
66
+ <p>The practical takeaway: don&#39;t run STM once and call it done. Run it, reset, tighten the bar, run it again. Two rounds got 89.5% on a tiny GRU doing addition. More rounds on bigger models, who knows.</p>
67
+ <p>Dragonoid said &quot;try third round hehehehehe&quot; so CompactAI did. Here&#39;s what happens when you push to three generations, measuring unseen hard accuracy at epoch 20 of each round:</p>
68
+ <ul>
69
+ <li>Gen 1: 9.2%</li>
70
+ <li>Gen 2: 29.6%</li>
71
+ <li>Gen 3: 30.8%</li>
72
+ </ul>
73
+ <p>So 3.2x jump from Gen 1 to 2, then only 1.2x from 2 to 3. Diminishing returns, but not terrible. The model&#39;s still squeezing a little more out of the data on that third pass. It&#39;s not nothing.</p>
74
+ <p>Compute savings tell a different story though. After fixing the mastery floor (the early 71.6% run had it cranked to 0.15, way too high), the actual numbers across rounds:</p>
75
+ <ul>
76
+ <li>One round: 1.8% saved</li>
77
+ <li>Two rounds: 4.0% saved</li>
78
+ <li>Three rounds: 21.2% saved</li>
79
+ </ul>
80
+ <p>Savings compound. The first round barely shrinks anything, the model&#39;s being conservative about what it tosses. By round three the model&#39;s confident enough to yeet a fifth of the dataset. The floor&#39;s doing its job.</p>
81
+ <p>The pattern&#39;s pretty clear at this point. First reset gives you a huge leap cause the model&#39;s weights have been fundamentally changed by the hard-data grinding. Second reset gives a smaller bump, the model&#39;s already close to its ceiling on this dataset.</p>
82
+ <h2>tldr</h2>
83
+ <ul>
84
+ <li>STM: each epoch, chuck the samples whose loss dropped the most. Train on what&#39;s left. Repeat.</li>
85
+ <li>Circling: the eval pass that figures out what to chuck</li>
86
+ <li>Big sudden drops = model already memorized it, further training&#39;s wasteful. Slow drops = still learning, keep those</li>
87
+ <li>Proven single-pass: 3.52x efficiency. Compute savings depend on mastery floor (71.6% with floor at 0.15, lower with saner settings). Script included.</li>
88
+ <li>Recursive STM (Dragonoid): reset dataset after full STM, do it again. Two rounds hit 89.5%, three rounds pushed unseen hard accuracy 9.2% → 29.6% → 30.8%. Compute savings compound: 1.8% → 4.0% → 21.2%.</li>
89
+ <li>Apollonian gasket circle thing is unrelated. Ask before you mix em up.</li>
90
+ </ul>
91
+ <hr>
92
+ <p><em>notes from the #general chat history. got something wrong? yell at me.</em></p>
93
+ </article>
94
+ <footer class="paper-credit" role="contentinfo"><span class="credit-label">Credit goes to Dragonoid (theory), CompactAI (proof) & the CompactAI crew</span>: <span class="credit-names"></span></footer>
95
+ </div>
96
+ </main>
97
+ </body>
98
+ </html>
Papers/apollonian_gasket-md.html ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Token Embeddings Inside an Integer Apollonian Gasket</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Geist:wght@300..700&family=Geist+Mono:wght@400;500&display=swap" rel="stylesheet">
10
+ <link rel="stylesheet" href="../everywhere.css">
11
+ </head>
12
+ <body>
13
+ <main class="container paper-page">
14
+ <div class="paper-page-shell">
15
+ <h1 class="paper-page-title">Token Embeddings Inside an Integer Apollonian Gasket</h1>
16
+ <div class="paper-page-meta">Mage · 2026-05</div>
17
+ <article class="paper-body" role="article" aria-label="Paper content"><h1>Token Embeddings Inside an Integer Apollonian Gasket</h1>
18
+ <p>OK so Mage keeps bringing this up in #general and honestly it&#39;s the kind of thing that sounds like math fanfiction until you sit there for twenty minutes and then you&#39;re like... wait. Maybe not completely insane.</p>
19
+ <p>The pitch: instead of learning token embeddings as giant float matrices through SGD, put every token as an address inside an Apollonian gasket, you know, that fractal you get when you recursively pack circles into the gaps between other circles forever, and key each address to a pair of twin primes.</p>
20
+ <p>I know. Stick with me.</p>
21
+ <h2>the geometry, roughly</h2>
22
+ <p>Apollonian gasket comes out of Descartes&#39; circle theorem. Four mutually tangent circles, their curvatures (1/radius) satisfy a quadratic relation. Start with three tangent circles, compute the two circles tangent to all three, pick one, recurse. You get this infinitely detailed fractal where every circle has an integer curvature. Provided you start with the right initial curvatures anyway.</p>
23
+ <p>Circles in an integer gasket form a hierarchy. Big circles = small curvatures. Deeper = bigger curvatures. Circles tangent to each other are neighbors. And a circle&#39;s curvature encodes something about where it sits in the hierarchy, its position relative to everything else. That&#39;s the part that matters.</p>
24
+ <h2>the twin prime thing (this is where it gets weird)</h2>
25
+ <p>Mage&#39;s actual suggestion: map each token to a circle via f: token → (p₁, p₂) where p₁ and p₂ are twin primes. Primes differing by exactly 2, like 17 and 19. The +2 gap between twin primes maps naturally onto the local step structure of the gasket. &quot;Semantic neighbors&quot; come for free from number theory instead of co-occurrence stats.</p>
26
+ <p>So the weight matrix, the thing that normally stores all the relationships between tokens as learned floats, becomes the curvature graph. Instead of &quot;the embedding for cat is related to the embedding for dog by some learned vector&quot; you get &quot;the curvature of cat&#39;s circle has a specific Descartes relation to the curvature of dog&#39;s circle.&quot;</p>
27
+ <p>Inference becomes bounded curvature recall: search circles with curvature ≤ K, filter by primality (make sure you&#39;re on valid addresses), verify Descartes-consistency (make sure geometric relations actually hold). It&#39;s deterministic. You&#39;re traversing a fixed structure, not predicting an embedding.</p>
28
+ <h2>wait, this might actually have something to it</h2>
29
+ <p>Few things from the back-and-forth in chat that make this better than your average 3am math thought:</p>
30
+ <p>The structure is fixed. Normal embeddings are a black box, train em, they go somewhere, hope the geometry&#39;s nice. Gasket geometry is given. The question becomes whether it&#39;s useful, not whether you can learn a useful one. Different problem entirely.</p>
31
+ <p>The twin prime mapping gives you a built-in closeness notion from number theory. Twin primes are conjectured infinite (unproven, sure, but more than enough for any practical vocab). And since they&#39;re spaced by exactly 2 you get a natural adjacency. Map semantically similar tokens to nearby primes and the geometry handles the rest.</p>
32
+ <p>And it&#39;s absurdly compressible. You don&#39;t store a giant embedding matrix. You store the gasket generation algorithm and the vocab-to-prime-pairs mapping. 50k vocabulary? 50k integer pairs instead of 50k × 768 floats. Hundreds of megabytes down to kilobytes. Maybe tens of kilobytes. That&#39;s wild.</p>
33
+ <h2>the problems that nobody&#39;s solved</h2>
34
+ <p>Plenty. The chat wasn&#39;t pretending otherwise.</p>
35
+ <p>Biggest one: how do you assign tokens to primes? Need a mapping from tokens to (p₁, p₂) pairs where semantically similar tokens end up near each other in the gasket. Random assignment = geometry is meaningless noise. But if you have to learn the assignment... you just moved the learning problem somewhere else. Nothing&#39;s free.</p>
36
+ <p>Also the gasket is 2D. Token embeddings are usually 768D or higher. You&#39;re cramming high-dimensional semantics into a flat fractal. There are ways to extend Descartes to higher dimensions (Soddy&#39;s theorem generalizes), but the nice integer properties of the Apollonian gasket are a 2D thing specifically.</p>
37
+ <p>&quot;Bounded curvature recall&quot; sounds neat, what&#39;s it actually mean for language modeling though? You&#39;re doing geometric lookup. How does attention even work here? Does attention make sense when &quot;embeddings&quot; are fixed positions?</p>
38
+ <p>And twin prime conjecture is unproven. If twin primes are somehow finite (almost certainly not but we can&#39;t prove it) you&#39;d run out of addresses. Even with infinite twin primes, the density thins, mapping a million tokens might force you into enormous primes and correspondingly enormous curvatures.</p>
39
+ <h2>building it (nobody has yet)</h2>
40
+ <p>Experiment would look like:</p>
41
+ <p>Pick a small vocab, maybe 1000 tokens. Manually assign em to twin prime pairs, doesn&#39;t have to be perfect, just needs semantically related ones geometrically close. Build a tiny transformer where embedding lookup is replaced by gasket traversal. Model doesn&#39;t learn embeddings, it learns to navigate the structure. Train on something simple like next token prediction. See if it converges at all.</p>
42
+ <p>Null hypothesis: it learns nothing useful cause the geometric prior is wrong. If it does learn? Interesting.</p>
43
+ <p>Compare to identical model with learned embeddings. If the gasket version is even in the same ballpark, that&#39;s a big deal given the compression advantage.</p>
44
+ <p>Mage suggested combining this with STM from the other paper, since you&#39;d want to be picky about training examples when your embedding scheme is this constrained. But honestly combining two untested ideas sounds like a great way to not know which one&#39;s failing.</p>
45
+ <h2>anyone done this before?</h2>
46
+ <p>I looked. Nope. No literature on Apollonian gaskets for token embeddings.</p>
47
+ <p>Nearest neighbors: hyperbolic embeddings (Poincaré ball) for hierarchies, but those are continuous, learned, no integer or prime structure. Some niche fractal initialization papers. Some knowledge graph stuff in hyperbolic/spherical geometries. Nothing using gaskets, twin primes, or curvature graphs as the embedding mechanism. Genuinely new ground. For better or worse.</p>
48
+ <h2>tldr</h2>
49
+ <ul>
50
+ <li>Tokens as circles in an integer Apollonian gasket, addressed by twin prime pairs</li>
51
+ <li>Semantic neighbors geometrically close cause of Descartes curvature relations</li>
52
+ <li>Weight matrix = curvature graph. Inference = curvature recall + primality filter + Descartes check</li>
53
+ <li>Kilobytes instead of hundreds of megabytes for the embedding table</li>
54
+ <li>Completely untested, might be mathematically impossible for high-dim semantics</li>
55
+ <li>If it worked even a little... worth writing home about</li>
56
+ </ul>
57
+ <hr>
58
+ </article>
59
+ <footer class="paper-credit" role="contentinfo"><span class="credit-label">Credit goes to Mage & CompactAI</span>: <span class="credit-names"></span></footer>
60
+ </div>
61
+ </main>
62
+ </body>
63
+ </html>
Papers/attention_experiment-md.html ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>An Experiment With Attention</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Geist:wght@300..700&family=Geist+Mono:wght@400;500&display=swap" rel="stylesheet">
10
+ <link rel="stylesheet" href="../everywhere.css">
11
+ </head>
12
+ <body>
13
+ <main class="container paper-page">
14
+ <div class="paper-page-shell">
15
+ <h1 class="paper-page-title">An Experiment With Attention</h1>
16
+ <div class="paper-page-meta">wop · 2026-05</div>
17
+ <article class="paper-body" role="article" aria-label="Paper content"><h1>An Experiment With Attention</h1>
18
+ <p>wop posted this on HuggingFace. Started simple: can you swap full attention for something cheaper and still keep enough context to nail the next token? Answer turned out to be &quot;nope, not yet&quot;, but how it got there is more interesting than the headline.</p>
19
+ <p>The setup is clean. Reproducible. Refreshing, no massive training runs, no &quot;promising directions&quot; handwaving. Just a concrete benchmark, two architectures, numbers.</p>
20
+ <h2>the actual question</h2>
21
+ <p>Context window isn&#39;t a flat sequence of tokens. It&#39;s usually: task instructions, style hints, formatting rules, actual content. These don&#39;t all matter at every token. Some rules are globally relevant but locally weak, the emoji rule in a system prompt, a formatting constraint. Model needs to carry them the whole way even when they don&#39;t matter at each individual prediction.</p>
22
+ <p>wop&#39;s framing: can a compressed context state preserve those weak early rules as the sequence gets long? And how does that stack up against ordinary attention?</p>
23
+ <h2>two models, head to head</h2>
24
+ <p>Attention: standard causal transformer attention. The baseline.</p>
25
+ <p>Compressed: replaces token-to-token attention with a learned compressed memory state, a few implicit slots.</p>
26
+ <p>Important: the compressed model doesn&#39;t classify tokens into categories. It reads tokens, updates a compact state, predicts from that state. Structure stays implicit. No hand-crafted &quot;this is a rule, this is content&quot; partitioning.</p>
27
+ <p>Dataset is synthetic and hardcoded (keeps it clean). Each example has two early rules, one item, a long distractor-filled prefix, and a target that requires recovering the early rules. The benchmark specifically stresses rule retention over distance, not general prediction.</p>
28
+ <p>Context lengths: 64, 256, 1028.</p>
29
+ <h2>what happened</h2>
30
+ <p>Attention won. On quality. And on speed. Didn&#39;t expect the speed part.</p>
31
+ <p>At ctx64: attention val_acc 0.938, rule_acc 0.906. Compressed: 0.699 and 0.492.</p>
32
+ <p>At ctx256: attention 0.757 val_acc, 0.581 rule_acc. Compressed: 0.633 and 0.358.</p>
33
+ <p>At ctx1028: attention 0.701 val_acc, 0.492 rule_acc. Compressed: 0.577 and 0.263.</p>
34
+ <p>Speed was brutal. ctx1028: attention finished in about 10 seconds. Compressed took about 230. So it was less accurate AND 23x slower. Oof.</p>
35
+ <h2>the lesson (not &quot;compression bad&quot;)</h2>
36
+ <p>People might see those numbers and go &quot;welp attention wins, pack it up.&quot; That&#39;d miss the point.</p>
37
+ <p>Naive compressed recurrent context doesn&#39;t automatically beat attention. Obvious now. Wasn&#39;t obvious going in, plenty of people assumed compressing context would help with long-range stuff because you&#39;re forcing a summary. Numbers say nope. Not unless you&#39;re real careful about how you compress.</p>
38
+ <p>Preserving weak parallel instructions is harder than keeping a rolling summary. The compressed model didn&#39;t just lose accuracy, it specifically tanked rule_acc. That&#39;s the game. Can you keep early constraints alive? Answer: not with a dumb bottleneck.</p>
39
+ <p>Full attention is still stupidly strong, even on a benchmark literally designed to break it. That&#39;s kind of wild. Task was built to punish attention and it still held up.</p>
40
+ <p>Also worth noting: the compressed model updates memory step-by-step in sequence order, tons of serial work. Attention gets all those optimized parallel kernels. Some of the speed gap is architecture, some is just the real world having better kernels for one approach.</p>
41
+ <h2>what this means</h2>
42
+ <p>wop doesn&#39;t over-claim. The motivating intuition, context isn&#39;t flat, some instructions matter globally but weakly, a good alternative to attention needs to preserve those signals, that&#39;s still solid. What broke is that the first compressed block was too simple. Formed a bottleneck. Just not a smart enough one.</p>
43
+ <p>If you wanna replace or relax attention, the replacement probably needs: a smarter way to preserve weak long-range constraints (rule_acc tells you directly if you&#39;re failing), a more parallel implementation (230 seconds is useless), a more selective memory update (not every token matters for those early constraints), and a benchmark that measures rule retention directly, not hidden inside average loss.</p>
44
+ <p>Next step: compress smarter, not harder.</p>
45
+ <h2>bottom line</h2>
46
+ <p>The experiment made the question concrete. No more abstract talk about &quot;efficient context.&quot; There&#39;s a clear picture now. Attention expensive but extremely effective. Compressed context alone isn&#39;t enough. Weak parallel instructions are a real stress test.</p>
47
+ <p>If cheaper context mechanisms are gonna work, they need to preserve global obligations without collapsing into a vague summary. Numbers are out there. Reproduce em or beat em.</p>
48
+ <p>wop used Kaggle notebooks for GPU, Codex from OpenAI for assistance, HuggingFace ZeroGPU for the thumbnail. Repo at github.com/koo1140/attention-experiment.</p>
49
+ <hr>
50
+ </article>
51
+ <footer class="paper-credit" role="contentinfo"><span class="credit-label">Credit goes to wop (poe) & CompactAI</span>: <span class="credit-names"></span></footer>
52
+ </div>
53
+ </main>
54
+ </body>
55
+ </html>
Papers/overta_hypothesis-md.html ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>The Overta Hypothesis: Knowledge-Free Foundation Models</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Geist:wght@300..700&family=Geist+Mono:wght@400;500&display=swap" rel="stylesheet">
10
+ <link rel="stylesheet" href="../everywhere.css">
11
+ </head>
12
+ <body>
13
+ <main class="container paper-page">
14
+ <div class="paper-page-shell">
15
+ <h1 class="paper-page-title">The Overta Hypothesis: Knowledge-Free Foundation Models</h1>
16
+ <div class="paper-page-meta">Amy · 2026-05</div>
17
+ <article class="paper-body" role="article" aria-label="Paper content"><h1>The Overta Hypothesis: Knowledge-Free Foundation Models</h1>
18
+ <p>Amy&#39;s been working on something that sounds backwards: train a language model from scratch that knows nothing about the world. Not &quot;knows less.&quot; Nothing. Model wouldn&#39;t know what a human is, wouldn&#39;t know Earth exists, wouldn&#39;t know what &quot;Paris&quot; or &quot;coffee&quot; or &quot;gravity&quot; means.</p>
19
+ <p>What it would know: how to reason. How to hold a conversation. How to use tools to look stuff up. How to do in-context learning from whatever you feed it at inference time.</p>
20
+ <p>OFM, Overta Foundation Model. She owns overta.org. Nothing on it yet, but the repo exists.</p>
21
+ <p>The pitch is basically: cramming world knowledge into weights, which every LLM since GPT-2 does, wastes parameters. Instead, let the model spend its entire budget on reasoning. Facts live outside, in retrievable documents. The model&#39;s just the engine.</p>
22
+ <h2>what does &quot;no world knowledge&quot; actually look like</h2>
23
+ <p>Weirder than you&#39;d think. When Amy says the model wouldn&#39;t know what a human is, she&#39;s literal. Here&#39;s the kind of definition she&#39;d provide externally at inference time, via search tool or context window:</p>
24
+ <blockquote>
25
+ <p>&quot;We are entities interacting with the physical world and able to do precise manipulation and also self-locomotion, through deforming and displacing our body.&quot;</p>
26
+ </blockquote>
27
+ <p>Model&#39;s never seen this before. Doesn&#39;t come pre-loaded. But it knows how to use a definition once provided. Knows how to reason from premises. If X is an entity that can manipulate objects and you ask about X&#39;s capabilities, it references the definition. That&#39;s the whole thing.</p>
28
+ <p>Training data would be purely synthetic conversations. Characters have defined properties stated explicitly in context. Reasoning chains spelled out step by step. Facts always grounded in explicitly provided info. Model never falls back on &quot;common sense&quot;, there isn&#39;t any.</p>
29
+ <p>Amy wrote seed examples by hand. The flavor:</p>
30
+ <pre><code>&lt;message from=&quot;other&quot;&gt;
31
+ describe whats happening now
32
+ &lt;/message&gt;
33
+ &lt;message from=&quot;self&quot;&gt;
34
+ &lt;think&gt;
35
+ They&#39;re asking me to describe &quot;whats happening now&quot;. Right now I&#39;m talking
36
+ to them and outputting text. I don&#39;t know of anything else happening now.
37
+ So I&#39;ll describe that to them.
38
+ &lt;/think&gt;
39
+ I (some entity which processes text and outputs text) am conversing with
40
+ you, what I assume to be an entity which also can process text and output
41
+ text of your own. I&#39;m outputting text to respond to your request.
42
+ &lt;/message&gt;
43
+ </code></pre>
44
+ <p>Notice it doesn&#39;t say &quot;I am an AI assistant.&quot; Says &quot;I (some entity which processes text and outputs text).&quot; Describes itself from first principles using only what&#39;s observable. The whole philosophy is in that one response.</p>
45
+ <h2>the arguments for it</h2>
46
+ <p>This crystallized across a bunch of conversations.</p>
47
+ <p>Hallucination isn&#39;t a bug, it&#39;s the design. LLMs hallucinate because they&#39;re trained to memorize facts and spit em back probabilistically. Don&#39;t train em to memorize facts, they can&#39;t hallucinate facts. They can still fail to reason correctly, different failure mode entirely.</p>
48
+ <p>Parameter efficiency. 350M model spending zero params on knowing the capital of France or the plot of Hamlet can spend all 350M on reasoning. Amy&#39;s guess: more intelligence per parameter than any model that mixes knowledge and reasoning.</p>
49
+ <p>Grounding is explicit. When the model uses a fact you know exactly where it came from, context window, search tool, user provided it. No mystery about whether the model&#39;s &quot;remembering&quot; or &quot;making it up.&quot;</p>
50
+ <p>Also updatability. World knowledge changes, models don&#39;t. Model with no world knowledge has nothing to go stale. Just update the retrieval database. And alignment: model with no priors about true/false, good/bad, normal/weird only knows what you tell it in the moment. The user defines the ethical frame and factual premises, not the training data. Which obviously cuts both ways, Amy&#39;s aware.</p>
51
+ <h2>and the problems</h2>
52
+ <p>Nobody&#39;s pulled it off yet. Amy&#39;s early experiments have been rough.</p>
53
+ <p>Language itself encodes knowledge, probably the biggest problem. Can&#39;t learn English grammar without incidentally learning that doctors treat patients, fire is hot, people have names. The boundary between &quot;reasoning&quot; and &quot;knowing&quot; is way blurrier than the hypothesis assumes. Costikoooo flagged this in chat: model might pick up unwanted world knowledge just from how conversations are structured.</p>
54
+ <p>Cold start is brutal. Amy&#39;s pipeline: manually write ~200 seed examples → finetune Qwen3 4B to generate more → use that for the full training dataset. Seed examples have to be near-perfect, everything cascades from em. Claude Opus &quot;doesn&#39;t get it even close first try and needs a lot of iterating.&quot; And the AI models she&#39;s using to generate training data were themselves trained on world knowledge, so they sneak it in. Recursive contamination basically.</p>
55
+ <p>Her earlier procedural generators, pure code, no LLMs, produced a model that could tool-call but was &quot;the most brittle thing imaginable.&quot; Only worked with names in its predefined list. Generalization terrible.</p>
56
+ <p>Then there&#39;s in-context bandwidth: if every fact has to live in the context window you need a killer retrieval system and model becomes only as good as its RAG. Dragonoid also asked about ethics, what even counts as knowledge? Dragonoid asked about ethics. Amy said ethics would be taught as abstract values. But are values knowledge? Where&#39;s the line? Gets tangled fast.</p>
57
+ <h2>the procedural generation thing</h2>
58
+ <p>Amy&#39;s earlier approach, and the more interesting one honestly, ditched LLMs entirely. She built a system of TypeScript generators. Each function handles one aspect of conversation generation. One generator adds a user message like &quot;My name is Joe,&quot; mutates conversation state so Joe&#39;s stored. Later generators reference that state. The system randomly chains generators together. All procedures, guaranteed consistent cause the state machine enforces it.</p>
59
+ <p>Trained a 350M model from scratch on this procedural data. Qwen3 architecture, custom tokenizer, about an hour per training run on a 16GB GPU. Model learned to remember user names (generator state tracked em), search for info it didn&#39;t have (generators included search calls), stay in character as &quot;an entity that processes text.&quot;</p>
60
+ <p>But brittle. Only generalized to names in the generator&#39;s list. Math broken. Longer training mighta helped, only about an hour per run.</p>
61
+ <p>Neat insight though: with this approach you add a new capability by writing a new generator and retraining. Timer? Timer generator. Spatial reasoning? Spatial generator. Capabilities are modular because the training data is modular.</p>
62
+ <p>And it&#39;s philosophically cleaner than LLM-distillation. No world knowledge leaks in. But way more labor, you&#39;re writing a program that writes programs that simulate conversations, and you gotta anticipate every capability.</p>
63
+ <h2>where this needs to go</h2>
64
+ <p>Viable experiment:</p>
65
+ <ol>
66
+ <li>Procedural generator covering ~20 distinct capabilities (name memory, search, clarification, multi-turn reasoning, simple math from provided formulas, etc.)</li>
67
+ <li>Train small model (~100M) from scratch only on this data</li>
68
+ <li>Test novel names, novel facts in context, novel combos of capabilities</li>
69
+ <li>Compare to identical model on standard web text, does Overta model hallucinate less? Reason worse? Something in between?</li>
70
+ </ol>
71
+ <p>Amy&#39;s paused this to work on other stuff but the repo and approach are documented. Someone could pick it up.</p>
72
+ <h2>tldr</h2>
73
+ <ul>
74
+ <li>Train a model that knows zero facts, only reasoning and conversation</li>
75
+ <li>All knowledge from context window or retrieval at inference time</li>
76
+ <li>Training data procedurally generated, not scraped</li>
77
+ <li>Claims: no hallucination (can&#39;t invent facts you never learned), better param efficiency, explicit grounding</li>
78
+ <li>Problems: language encodes knowledge, procedural generation is labor-intensive, model brittle so far</li>
79
+ <li>Amy poked at this with 350M models, promising, not there yet</li>
80
+ </ul>
81
+ <hr>
82
+ </article>
83
+ <footer class="paper-credit" role="contentinfo"><span class="credit-label">Credit goes to Amy & the CompactAI server</span>: <span class="credit-names"></span></footer>
84
+ </div>
85
+ </main>
86
+ </body>
87
+ </html>
Papers/sparrow_fant-md.html ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Sparrow, FANT, and the Weird Stuff That Works</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Geist:wght@300..700&family=Geist+Mono:wght@400;500&display=swap" rel="stylesheet">
10
+ <link rel="stylesheet" href="../everywhere.css">
11
+ </head>
12
+ <body>
13
+ <main class="container paper-page">
14
+ <div class="paper-page-shell">
15
+ <h1 class="paper-page-title">Sparrow, FANT, and the Weird Stuff That Works</h1>
16
+ <div class="paper-page-meta">Crownelius · 2026-05</div>
17
+ <article class="paper-body" role="article" aria-label="Paper content"><h1>Sparrow, FANT, and the Weird Stuff That Works</h1>
18
+ <p>Shane (Crownelius) posted this on HuggingFace after sitting on the story. It&#39;s part technical writeup, part personal history, part challenge. Here&#39;s a bunch of half-built things, some of them work way better than they should, come help figure out why.</p>
19
+ <p>The headline: Sparrow, a 1M-parameter model, scores 95.6% on a 1,900-question math eval where Owl Alpha scores 61.4%. One million parameters versus a 70B-class model. Not a typo.</p>
20
+ <h2>how Shane got here</h2>
21
+ <p>Unusual route into model building. Dropped a finetune that scored weirdly high on EQ, the empathy benchmark nobody goes after. Publishing outfit reached out, wanted full books generated through Claude, architected prompt-by-prompt. Gig ran over $25k in API credits. Shane designed every prompt. About 60% of that publisher&#39;s pipeline still uses his curation.</p>
22
+ <p>That flipped him from using models to building em. Tiny ones specifically, small enough for a 12GB card, small enough that every architectural choice is exposed and wrong decisions are embarrassing.</p>
23
+ <h2>FANT and stuff that shouldn&#39;t work</h2>
24
+ <p>FANT (github.com/Crownelius/fant3) is the experimentation framework. Three iterations, each a full rewrite, the kind you do when you care about findings, not code. Philosophy: at small scale you can try genuinely dumb ideas and actually see what they do. No hiding behind scale.</p>
25
+ <p>The standout: SleepGate. A memory consolidation routine that fires every 100 training steps. Like half a screen of code, mostly comments. On FANT 2 at 5M parameters, 1,000-problem procedural math eval: +5.3 points. From one architectural decision. Same optimizer, same data, same schedule. Just a tiny consolidation pass wedged in.</p>
26
+ <p>Why does that move the needle that much? Nobody&#39;s fully sure. But it does. That&#39;s the point of the framework, surface weird stuff so people can dig in.</p>
27
+ <h2>SpinorApollonian Memory (this is the newest weird thing)</h2>
28
+ <p>This one needs setup. Shane found a paper by Jerzy Kocik on tangency spinors, classifying Apollonian disk packings using 2D Minkowski spinors. Descartes&#39; circle theorem turns out to be the Minkowski quadratic form in signature (1,3). Actual math, not metaphor.</p>
29
+ <p>Application: memory writes get split by chirality. Left-spinning packs go to one bucket, right-spinning packs to another. Geometric routing instead of threshold routing.</p>
30
+ <p>The failure mode that&#39;d been a problem for two months, packs starving each other into uselessness, just vanished. Same pattern at every scale tested, 5M through 742M. Hard to believe. But the ablation table doesn&#39;t lie.</p>
31
+ <p>&quot;Sounds like peanut butter on a hamburger, but the ablation table says it works.&quot;, Shane</p>
32
+ <h2>Sparrow vs Owl Alpha</h2>
33
+ <p>Sparrow is separate from FANT. Different skeleton, different router, different everything. Small and surgical, built for math. Not general-purpose, not trying to be.</p>
34
+ <p>Across 38 head-to-head evals (n=50 each, numeric scoring), Sparrow ties or beats Owl Alpha on 33 of 38. 87%.</p>
35
+ <p>Five losses are on simple multiplication and division at digit counts where Owl&#39;s training data is dense. Fair wins, not the interesting ones.</p>
36
+ <p>The interesting ones: Goldbach, Collatz, Fermat-little, complex modulus, dot products, distance, determinants. +100 percentage points in some cases. +98pp. +88pp.</p>
37
+ <p>A 1M-parameter byte-level model beating a 70B-class frontier model by margins you&#39;d normally assume are bugs. Shane checked twice, bothered three friends, re-ran at three temperatures. Same numbers. Makes you question how much of big-model performance is just brute force.</p>
38
+ <p>Trick: Sparrow uses a calc-tag wrapper for arithmetic. It learns to call it correctly. 5-digit multiplication: Owl Alpha 12%, Gemma 3 27B 0%, Sparrow 100%. Model doesn&#39;t do math, learns to use the tool. That&#39;s the whole thing.</p>
39
+ <h2>unsolved: FANT + Sparrow fusion</h2>
40
+ <p>Shane can&#39;t get Sparrow&#39;s approach to work with FANT&#39;s architecture. Something about how Sparrow handles symbolic state should connect to FANT&#39;s recursion stack, but the fusion&#39;s been elusive for weeks. Breadcrumbs are public, repo&#39;s open, issues are open, the challenge is sitting there.</p>
41
+ <p>&quot;Half-built spaceships are best shared.&quot;</p>
42
+ <h2>tldr</h2>
43
+ <ul>
44
+ <li>FANT: experimentation framework for tiny models (5M–742M)</li>
45
+ <li>SleepGate: 100-step consolidation pass, +5.3 points. Nobody knows exactly why</li>
46
+ <li>SpinorApollonian Memory: geometric routing by chirality using Minkowski spinors, killed a starvation bug</li>
47
+ <li>Sparrow: 1M-param math model beats Owl Alpha (70B-class) on 87% of evals. Not a typo</li>
48
+ <li>Trick is tool use (calc-tag), not raw compute, Sparrow calls for help</li>
49
+ <li>FANT + Sparrow fusion unsolved, open challenge</li>
50
+ </ul>
51
+ <hr>
52
+ </article>
53
+ <footer class="paper-credit" role="contentinfo"><span class="credit-label">Credit goes to Crownelius (Shane) & CompactAI</span>: <span class="credit-names"></span></footer>
54
+ </div>
55
+ </main>
56
+ </body>
57
+ </html>
Papers/trueact-md.html ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>TrueACT: A Different Kind of Neuron</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Geist:wght@300..700&family=Geist+Mono:wght@400;500&display=swap" rel="stylesheet">
10
+ <link rel="stylesheet" href="../everywhere.css">
11
+ </head>
12
+ <body>
13
+ <main class="container paper-page">
14
+ <div class="paper-page-shell">
15
+ <h1 class="paper-page-title">TrueACT: A Different Kind of Neuron</h1>
16
+ <div class="paper-page-meta">CompactAI · 2026-05</div>
17
+ <article class="paper-body" role="article" aria-label="Paper content"><h1>TrueACT: A Different Kind of Neuron</h1>
18
+ <p>Transformers use the same MLP on every token. Every time. Same weights, same math, no memory of where it&#39;s been in the sequence, no sense of how confident it is. TrueACT chucks that. Replaces the MLP with a small recurrent block that loops. Reads the token, updates a hidden state, checks if it&#39;s confident enough, either answers or loops again. Keeps going til it hits 0.99 confidence or runs out of steps.</p>
19
+ <p>It&#39;s not a standard neuron. It&#39;s not an attention head. It&#39;s a loop with a router that picks between four specialized operations depending on what the token needs.</p>
20
+ <p>Half the parameters of the equivalent standard model. Same loss. 2.8x slower cause of the loop. You&#39;re trading flops for parameter efficiency.</p>
21
+ <h2>the four experts</h2>
22
+ <p>Each TrueACT layer has four experts. The router picks which combination to use per token, not per layer. So different tokens in the same batch can fire different experts. Here&#39;s what they do:</p>
23
+ <p><strong>Think Cell</strong> — this is the actual recurrent part. Updates the latent state, which is basically working memory that persists across steps within the same layer. Think of it like scratch paper the model scribbles on while reasoning.</p>
24
+ <p><strong>Standard</strong> — plain linear pattern matching. Same job the normal MLP would do. Catches the easy stuff.</p>
25
+ <p><strong>Fancy</strong> — this is the weird one. Does math in log-space. For multiplication, <code>log(a*b) = log(a) + log(b)</code>. Addition is something a linear layer can already do. So instead of needing a pile of neurons to approximate a multiplication curve, one Fancy expert can do it cleanly. Log then add then exp. Multiplication, division, ratios, chained operations.</p>
26
+ <p><strong>Memory Vault</strong> — key → value associative lookup. A dedicated place to store facts instead of smearing them across all the weights. Retrieve, don&#39;t approximate.</p>
27
+ <p>The router takes <code>[input, latent_state, step_count]</code>, sticks it through a linear layer plus softmax, and that&#39;s the expert selection. Standard and Fancy spend from an action budget. Once the budget is gone, the loop stops, unless it hits the 32-step cap.</p>
28
+ <h2>why this works</h2>
29
+ <p>A standard transformer neuron is a linear approximator. For something like <code>a * b = c</code>, you&#39;d need a big pile of neurons approximating a curve. It works eventually but it&#39;s wasteful. The weights end up encoding the same multiplication table across hundreds of parameters, and there&#39;s no clean way to just <em>do the math</em>.</p>
30
+ <p>The Fancy expert sidesteps that. Goes to log-space, adds, comes back. One neuron doing what used to take a crowd.</p>
31
+ <p>The Memory Vault is the same idea from the other direction. Instead of memorizing facts by storing them implicitly in weight matrices, just do a key-value lookup. Store it once, retrieve it when needed.</p>
32
+ <p>The Think Cell ties it together. Gives the model a place to hold intermediate state while it loops through the experts. Without it, each token is a one-shot guess. With it, the model can go &quot;hmm let me think about this&quot; and take another step.</p>
33
+ <p>So the model gets more mileage per parameter. The tradeoff is sequential compute. You can&#39;t parallelize a loop that depends on its own output. That&#39;s where the 2.8x slowdown comes from.</p>
34
+ <h2>the numbers</h2>
35
+ <p>3-layer LLaMA-style comparison at d=384:</p>
36
+ <table>
37
+ <thead>
38
+ <tr>
39
+ <th>metric</th>
40
+ <th>Standard</th>
41
+ <th>TrueACT</th>
42
+ </tr>
43
+ </thead>
44
+ <tbody><tr>
45
+ <td>loss</td>
46
+ <td>0.0884</td>
47
+ <td>0.0880</td>
48
+ </tr>
49
+ <tr>
50
+ <td>params</td>
51
+ <td>852,864</td>
52
+ <td>428,652</td>
53
+ </tr>
54
+ <tr>
55
+ <td>train speed</td>
56
+ <td>1x</td>
57
+ <td>2.8x slower</td>
58
+ </tr>
59
+ </tbody></table>
60
+ <p>Same loss, roughly half the weights. The slowdown is real — the loop is sequential, can&#39;t be parallelized. But you&#39;re getting the same quality out of half the parameter budget.</p>
61
+ <p>1-layer arithmetic reasoner: 12/12 on a fixed 12-expression benchmark. 91.6% on 500 random expressions. The misses are mostly multi-digit arithmetic — <code>42*88=3524</code> type stuff. Structure like parentheses, operator precedence, intermediate steps — those come out clean. The model actually writes out the worked steps: <code>((5*5)+(10*2))=(25+(10*2))=(25+20)=45|</code></p>
62
+ <h2>the router in action</h2>
63
+ <p>The routing stats tell you what the model&#39;s doing under the hood. Example from the inference CLI:</p>
64
+ <pre><code>Prompt &gt; ((5*5)+(10*2))=
65
+ TrueACT : ((5*5)+(10*2))=(25+(10*2))=(25+20)=45|
66
+ [Think: 15% | Stand: 30% | Fancy: 45% | Vault: 10%]
67
+ </code></pre>
68
+ <p>For arithmetic, Fancy gets most of the budget. Makes sense — multiplication is the expensive operation and Fancy handles it in log-space. Standard catches the easy pattern matching (digits, parens, equals signs). Think Cell does the state tracking across steps. Memory Vault probably handles the number facts.</p>
69
+ <p>The router isn&#39;t pre-programmed. It learns which expert to use for which kind of token during training. The routing stats are emergent.</p>
70
+ <h2>how training works</h2>
71
+ <p>Data is an infinite stream of generated arithmetic — <code>+</code>, <code>-</code>, <code>*</code>, parentheses, multi-step chains. Format is <code>((5*5)+(10*2))=(25+(10*2))=(25+20)=45|</code>. The model sees a random position in the chain and has to predict the next character.</p>
72
+ <p>Context window is 64 chars, one-hot encoded. The alphabet is 12 characters (digits, operators, parens, equals, pipe) so the input is 768-dimensional one-hots.</p>
73
+ <p>Batch size 8192. AdamW, lr 5e-4, weight decay 0.01. 1-3 layer TrueACTStack, t_dim=256, max 32 ACT steps per layer.</p>
74
+ <p>Training also runs a StandardStack (same structure, ordinary SiLU MLPs) side by side as the control group. Checkpoints save both every 500 steps.</p>
75
+ <h2>the architecture, deeper</h2>
76
+ <p><strong>TrueACTLayer</strong>: concat input x and latent h → xh. Router reads <code>[xh, step_frac]</code> → softmax over 4 experts. Compute expert outputs, gate by <code>router_prob * remaining_budget</code>, accumulate into the result, update h through the Think Cell. Repeat til budget hits zero or 32 steps.</p>
77
+ <p><strong>TrueACTStack</strong>: N of those layers with residual connections. Input projection to model dim at the bottom, output projection to vocab at the top.</p>
78
+ <p><strong>StandardStack</strong>: same structure but with normal SiLU MLPs instead of the TrueACT loop. The control group.</p>
79
+ <p>The budget mechanism matters. Standard and Fancy both consume budget when used. Think Cell and Memory Vault, from how they&#39;re structured, seem to be state management rather than compute, so they don&#39;t appear to draw from the budget. The model can think (Think Cell) and retrieve (Memory Vault) freely. Only the expensive ops cost steps.</p>
80
+ <h2>how it started</h2>
81
+ <p>This thing began as one log-space neuron trying to learn <code>x*y=z</code>. That&#39;s it. One neuron doing multiplication in log-space.</p>
82
+ <p>41 notes later in MEMORY.md. Mode collapse. Gradient explosions. Dead architecture after dead architecture. Full rewrites. Things that almost worked before falling apart at higher dimensions.</p>
83
+ <p>The 41 notes on what didn&#39;t work are arguably more valuable than what did. Every dead end, every fix, every &quot;wait that shouldn&#39;t have helped&quot; moment. Built for AI agents to read so they don&#39;t repeat the same mistakes.</p>
84
+ <p>The four-expert router, the Think Cell, the budget gating, the step cap — none of that was in the original idea. Each piece got added because something broke without it.</p>
85
+ <h2>looking forward</h2>
86
+ <p>The toy results are promising. Half the params, same loss. The next step is figuring out if this scales past small arithmetic models, and what the loop overhead looks like at bigger sizes. That&#39;s the open question.</p>
87
+ <hr>
88
+ <p><em>the 41st attempt finally worked. go read MEMORY.md if you wanna avoid the first 40.</em></p>
89
+ <h2>tldr</h2>
90
+ <ul>
91
+ <li>Swap the transformer MLP for a recurrent block that loops til it&#39;s confident</li>
92
+ <li>Four experts: Think Cell (working memory), Standard (linear matching), Fancy (log-space math), Memory Vault (key→value lookup)</li>
93
+ <li>Router picks which experts fire per token based on input, latent state, and step count</li>
94
+ <li>Half the params (429k vs 853k), same loss (0.0880 vs 0.0884), 2.8x slower</li>
95
+ <li>1-layer solves 12/12 on fixed benchmark, 91.6% on 500 random arithmetic expressions</li>
96
+ <li>Fancy expert does <code>log(a*b) = log(a)+log(b)</code> — one neuron doing what used to take a crowd</li>
97
+ <li>Started as one log-space neuron, 41 failed notes later it&#39;s a whole architecture</li>
98
+ <li>Tradeoff: sequential compute for parameter efficiency</li>
99
+ </ul>
100
+ <hr>
101
+ <p><em>the 41st attempt finally worked. go read MEMORY.md if you wanna avoid the first 40.</em></p>
102
+ </article>
103
+ <footer class="paper-credit" role="contentinfo"><span class="credit-label">Credit goes to CompactAI</span>: <span class="credit-names"></span></footer>
104
+ </div>
105
+ </main>
106
+ </body>
107
+ </html>
everywhere.css ADDED
@@ -0,0 +1,803 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ *,
3
+ *::before,
4
+ *::after {
5
+ margin: 0;
6
+ padding: 0;
7
+ box-sizing: border-box;
8
+ }
9
+
10
+ :root {
11
+ --bg: #000000;
12
+ --bg-card: #0a0a0a;
13
+ --bg-card-hover: #0f0f0f;
14
+ --border-card: #1a1a1a;
15
+ --text: #ffffff;
16
+ --text-soft: #f5f5f5;
17
+ --text-muted: #888888;
18
+ --text-dim: #555555;
19
+ --accent: #c8960c;
20
+ --accent-bright: #ffd633;
21
+ --accent-muted: #8b6508;
22
+ --gold-gradient: linear-gradient(135deg, #ffd633 0%, #c8960c 50%, #a0760a 100%);
23
+ --grid-line: rgba(255, 255, 255, 0.03);
24
+ --grid-line-major: rgba(255, 255, 255, 0.06);
25
+ --container-max: none;
26
+ }
27
+
28
+ html {
29
+ scroll-behavior: smooth;
30
+ background: var(--bg);
31
+ }
32
+
33
+ /* ---- Focus styles ---- */
34
+ :focus-visible {
35
+ outline: 2px solid var(--accent-bright);
36
+ outline-offset: 3px;
37
+ border-radius: 4px;
38
+ }
39
+
40
+ .paper-card:focus-visible {
41
+ outline: 2px solid var(--accent-bright);
42
+ outline-offset: 2px;
43
+ border-radius: 12px;
44
+ }
45
+
46
+ .paper-view-close:focus-visible {
47
+ outline: 2px solid var(--accent-bright);
48
+ outline-offset: 2px;
49
+ border-radius: 8px;
50
+ }
51
+
52
+ /* ---- Skip link ---- */
53
+ .skip-link {
54
+ position: fixed;
55
+ top: 0;
56
+ left: 0;
57
+ z-index: 200;
58
+ padding: 12px 20px;
59
+ background: var(--accent);
60
+ color: #000;
61
+ font-family: 'Geist', sans-serif;
62
+ font-size: 14px;
63
+ font-weight: 600;
64
+ text-decoration: none;
65
+ border-radius: 0 0 8px 0;
66
+ transform: translateY(-100%);
67
+ transition: transform 0.15s ease;
68
+ }
69
+
70
+ .skip-link:focus {
71
+ transform: translateY(0);
72
+ }
73
+
74
+ /* ---- Screen reader only ---- */
75
+ .sr-only {
76
+ position: absolute;
77
+ width: 1px;
78
+ height: 1px;
79
+ padding: 0;
80
+ margin: -1px;
81
+ overflow: hidden;
82
+ clip: rect(0, 0, 0, 0);
83
+ white-space: nowrap;
84
+ border: 0;
85
+ }
86
+
87
+ /* ---- Reduced motion ---- */
88
+ @media (prefers-reduced-motion: reduce) {
89
+ *,
90
+ *::before,
91
+ *::after {
92
+ animation-duration: 0.01ms !important;
93
+ animation-iteration-count: 1 !important;
94
+ transition-duration: 0.01ms !important;
95
+ }
96
+
97
+ html {
98
+ scroll-behavior: auto;
99
+ }
100
+ }
101
+
102
+ body {
103
+ background: var(--bg);
104
+ color: var(--text);
105
+ font-family: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
106
+ font-size: 16px;
107
+ font-weight: 350;
108
+ line-height: 1.7;
109
+ min-height: 100vh;
110
+ position: relative;
111
+ overflow-x: hidden;
112
+ }
113
+
114
+ /* ---- Dot grid background ---- */
115
+ body::before {
116
+ content: '';
117
+ position: fixed;
118
+ inset: 0;
119
+ pointer-events: none;
120
+ z-index: 0;
121
+ background-image:
122
+ radial-gradient(circle, var(--grid-line) 1px, transparent 1px);
123
+ background-size: 40px 40px;
124
+ mask-image: radial-gradient(ellipse 70% 70% at 50% 0%, black 30%, transparent 70%);
125
+ -webkit-mask-image: radial-gradient(ellipse 70% 70% at 50% 0%, black 30%, transparent 70%);
126
+ }
127
+
128
+ body::after {
129
+ content: '';
130
+ position: fixed;
131
+ inset: 0;
132
+ pointer-events: none;
133
+ z-index: 0;
134
+ background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.02'/%3E%3C/svg%3E");
135
+ opacity: 0.4;
136
+ }
137
+
138
+ /* ---- Container ---- */
139
+ .container {
140
+ position: relative;
141
+ z-index: 1;
142
+ max-width: var(--container-max);
143
+ margin: 0 auto;
144
+ padding: 0 40px;
145
+ }
146
+
147
+ /* ---- Header ---- */
148
+ .site-header {
149
+ padding: 80px 0 48px;
150
+ text-align: center;
151
+ position: relative;
152
+ }
153
+
154
+ .site-title {
155
+ font-family: 'Geist', sans-serif;
156
+ font-size: clamp(48px, 8vw, 80px);
157
+ font-weight: 700;
158
+ letter-spacing: -0.03em;
159
+ line-height: 1.05;
160
+ color: var(--text);
161
+ animation: fadeUp 0.8s ease-out both;
162
+ }
163
+
164
+ .site-title .gold {
165
+ background: var(--gold-gradient);
166
+ -webkit-background-clip: text;
167
+ -webkit-text-fill-color: transparent;
168
+ background-clip: text;
169
+ }
170
+
171
+ .site-subtitle {
172
+ font-family: 'Geist Mono', monospace;
173
+ font-size: 13px;
174
+ font-weight: 400;
175
+ letter-spacing: 0.12em;
176
+ text-transform: uppercase;
177
+ color: var(--text-dim);
178
+ margin-top: 16px;
179
+ animation: fadeUp 0.8s 0.15s ease-out both;
180
+ }
181
+
182
+ .header-divider {
183
+ width: 60px;
184
+ height: 1px;
185
+ background: var(--gold-gradient);
186
+ margin: 32px auto 0;
187
+ opacity: 0.5;
188
+ animation: fadeUp 0.8s 0.2s ease-out both;
189
+ }
190
+
191
+ @keyframes fadeUp {
192
+ from { opacity: 0; transform: translateY(20px); }
193
+ to { opacity: 1; transform: translateY(0); }
194
+ }
195
+
196
+ /* ---- Section label ---- */
197
+ .section-label {
198
+ font-family: 'Geist Mono', monospace;
199
+ font-size: 11px;
200
+ font-weight: 500;
201
+ letter-spacing: 0.14em;
202
+ text-transform: uppercase;
203
+ color: var(--text-dim);
204
+ margin-bottom: 24px;
205
+ padding-left: 2px;
206
+ }
207
+
208
+ /* ---- Paper Grid ---- */
209
+ .papers-grid {
210
+ display: grid;
211
+ grid-template-columns: repeat(3, 1fr);
212
+ gap: 28px;
213
+ padding-bottom: 96px;
214
+ list-style: none;
215
+ }
216
+
217
+ @media (max-width: 1100px) {
218
+ .papers-grid {
219
+ grid-template-columns: repeat(2, 1fr);
220
+ }
221
+ }
222
+
223
+ @media (max-width: 600px) {
224
+ .papers-grid {
225
+ grid-template-columns: 1fr;
226
+ }
227
+ }
228
+
229
+ /* ---- Paper Card (catalog) ---- */
230
+ .paper-card {
231
+ position: relative;
232
+ background: var(--bg-card);
233
+ border: 1px solid var(--border-card);
234
+ border-radius: 12px;
235
+ padding: 32px 36px;
236
+ cursor: pointer;
237
+ min-height: 180px;
238
+ display: flex;
239
+ flex-direction: column;
240
+ justify-content: space-between;
241
+ transition: all 0.35s ease;
242
+ overflow: hidden;
243
+ animation: fadeUp 0.6s ease-out both;
244
+ }
245
+
246
+ .paper-card::before {
247
+ content: '';
248
+ position: absolute;
249
+ inset: 0;
250
+ border-radius: 12px;
251
+ background: radial-gradient(
252
+ 600px circle at var(--mx, 50%) var(--my, 50%),
253
+ rgba(200, 150, 12, 0.06),
254
+ transparent 40%
255
+ );
256
+ opacity: 0;
257
+ transition: opacity 0.4s ease;
258
+ pointer-events: none;
259
+ }
260
+
261
+ .paper-card:hover {
262
+ border-color: rgba(200, 150, 12, 0.3);
263
+ background: var(--bg-card-hover);
264
+ transform: translateY(-2px);
265
+ box-shadow:
266
+ 0 20px 60px rgba(0, 0, 0, 0.4),
267
+ 0 0 0 1px rgba(200, 150, 12, 0.08);
268
+ }
269
+
270
+ .paper-card:hover::before {
271
+ opacity: 1;
272
+ }
273
+
274
+ .paper-card:active {
275
+ transform: translateY(0);
276
+ transition: all 0.1s ease;
277
+ }
278
+
279
+ .card-title {
280
+ font-family: 'Geist', sans-serif;
281
+ font-size: 20px;
282
+ font-weight: 600;
283
+ letter-spacing: -0.02em;
284
+ line-height: 1.3;
285
+ color: var(--text);
286
+ margin-bottom: 10px;
287
+ }
288
+
289
+ .card-author {
290
+ font-family: 'Geist Mono', monospace;
291
+ font-size: 11px;
292
+ font-weight: 500;
293
+ letter-spacing: 0.06em;
294
+ color: var(--accent-muted);
295
+ margin-bottom: 8px;
296
+ }
297
+
298
+ .card-meta {
299
+ display: flex;
300
+ align-items: center;
301
+ gap: 12px;
302
+ font-family: 'Geist Mono', monospace;
303
+ font-size: 12px;
304
+ color: var(--text-dim);
305
+ }
306
+
307
+ .card-tag {
308
+ font-family: 'Geist Mono', monospace;
309
+ font-size: 10px;
310
+ font-weight: 500;
311
+ letter-spacing: 0.08em;
312
+ text-transform: uppercase;
313
+ color: var(--accent-muted);
314
+ background: rgba(200, 150, 12, 0.08);
315
+ padding: 3px 8px;
316
+ border-radius: 4px;
317
+ border: 1px solid rgba(200, 150, 12, 0.12);
318
+ }
319
+
320
+ .card-proved {
321
+ font-family: 'Geist Mono', monospace;
322
+ font-size: 10px;
323
+ font-weight: 600;
324
+ letter-spacing: 0.08em;
325
+ text-transform: uppercase;
326
+ color: #1a7a1a;
327
+ background: rgba(26, 122, 26, 0.1);
328
+ padding: 3px 10px;
329
+ border-radius: 4px;
330
+ border: 1px solid rgba(26, 122, 26, 0.2);
331
+ flex-shrink: 0;
332
+ }
333
+
334
+ /* ---- Featured card ---- */
335
+ .paper-card.featured {
336
+ grid-column: 1 / -1;
337
+ padding: 48px 56px;
338
+ min-height: 220px;
339
+ border-color: color-mix(in srgb, var(--accent) 25%, transparent);
340
+ background: radial-gradient(ellipse 70% 50% at 50% 0%, rgba(200, 150, 12, 0.04), transparent 60%), var(--bg-card);
341
+ }
342
+
343
+ .paper-card.featured .card-title {
344
+ font-size: 28px;
345
+ letter-spacing: -0.03em;
346
+ }
347
+
348
+ .paper-card.featured .card-author {
349
+ font-size: 12px;
350
+ margin-bottom: 12px;
351
+ }
352
+
353
+ .paper-card.featured .card-meta {
354
+ font-size: 13px;
355
+ }
356
+
357
+ .paper-card.featured:hover {
358
+ border-color: color-mix(in srgb, var(--accent) 45%, transparent);
359
+ background: radial-gradient(ellipse 70% 50% at 50% 0%, rgba(200, 150, 12, 0.07), transparent 60%), var(--bg-card-hover);
360
+ }
361
+
362
+ @media (max-width: 640px) {
363
+ .paper-card.featured {
364
+ padding: 28px 24px;
365
+ min-height: 160px;
366
+ }
367
+
368
+ .paper-card.featured .card-title {
369
+ font-size: 22px;
370
+ }
371
+ }
372
+
373
+ /* ---- Proof script in paper view ---- */
374
+ .proof-section {
375
+ margin-top: 32px;
376
+ padding-top: 24px;
377
+ border-top: 1px solid var(--border-card);
378
+ }
379
+
380
+ .proof-label {
381
+ font-family: 'Geist Mono', monospace;
382
+ font-size: 11px;
383
+ font-weight: 600;
384
+ letter-spacing: 0.1em;
385
+ text-transform: uppercase;
386
+ color: #1a7a1a;
387
+ margin-bottom: 14px;
388
+ }
389
+
390
+ .proof-script {
391
+ background: rgba(0, 0, 0, 0.4);
392
+ border: 1px solid var(--border-card);
393
+ border-radius: 8px;
394
+ padding: 20px 24px;
395
+ overflow-x: auto;
396
+ font-family: 'Geist Mono', monospace;
397
+ font-size: 12px;
398
+ line-height: 1.6;
399
+ color: var(--text-muted);
400
+ tab-size: 4;
401
+ max-height: 500px;
402
+ overflow-y: auto;
403
+ }
404
+
405
+ .proof-script::-webkit-scrollbar {
406
+ width: 6px;
407
+ height: 6px;
408
+ }
409
+
410
+ .proof-script::-webkit-scrollbar-track {
411
+ background: transparent;
412
+ }
413
+
414
+ .proof-script::-webkit-scrollbar-thumb {
415
+ background: var(--border-card);
416
+ border-radius: 3px;
417
+ }
418
+
419
+ .card-arrow {
420
+ position: absolute;
421
+ right: 24px;
422
+ top: 50%;
423
+ transform: translateY(-50%);
424
+ font-size: 20px;
425
+ color: var(--text-dim);
426
+ opacity: 0;
427
+ transition: all 0.3s ease;
428
+ }
429
+
430
+ .paper-card:hover .card-arrow {
431
+ opacity: 1;
432
+ color: var(--accent);
433
+ }
434
+
435
+ /* ---- Modal / Paper View ---- */
436
+ .paper-overlay {
437
+ position: fixed;
438
+ inset: 0;
439
+ z-index: 100;
440
+ background: rgba(0, 0, 0, 0.9);
441
+ backdrop-filter: blur(12px);
442
+ -webkit-backdrop-filter: blur(12px);
443
+ display: flex;
444
+ align-items: flex-start;
445
+ justify-content: center;
446
+ padding: 0;
447
+ overflow-y: auto;
448
+ animation: overlayIn 0.25s ease-out;
449
+ }
450
+
451
+ @keyframes overlayIn {
452
+ from { opacity: 0; }
453
+ to { opacity: 1; }
454
+ }
455
+
456
+ .paper-view {
457
+ background: #0d0d0d;
458
+ border: none;
459
+ border-radius: 0;
460
+ max-width: none;
461
+ width: 100%;
462
+ min-height: 100vh;
463
+ padding: 64px clamp(32px, 8vw, 120px) 80px;
464
+ position: relative;
465
+ animation: modalIn 0.35s ease-out;
466
+ box-shadow: none;
467
+ }
468
+
469
+ .paper-view-frame {
470
+ display: block;
471
+ width: 100%;
472
+ min-height: calc(100vh - 144px);
473
+ border: 0;
474
+ background: transparent;
475
+ }
476
+
477
+ @keyframes modalIn {
478
+ from { opacity: 0; transform: translateY(24px) scale(0.97); }
479
+ to { opacity: 1; transform: translateY(0) scale(1); }
480
+ }
481
+
482
+ .paper-view-close {
483
+ position: fixed;
484
+ top: 24px;
485
+ right: 24px;
486
+ width: 40px;
487
+ height: 40px;
488
+ border-radius: 8px;
489
+ border: 1px solid var(--border-card);
490
+ background: rgba(10, 10, 10, 0.9);
491
+ backdrop-filter: blur(8px);
492
+ -webkit-backdrop-filter: blur(8px);
493
+ color: var(--text-muted);
494
+ cursor: pointer;
495
+ display: flex;
496
+ align-items: center;
497
+ justify-content: center;
498
+ font-size: 20px;
499
+ font-family: 'Geist Mono', monospace;
500
+ transition: all 0.2s ease;
501
+ z-index: 10;
502
+ }
503
+
504
+ .paper-view-close:hover {
505
+ border-color: rgba(200, 150, 12, 0.4);
506
+ color: var(--accent);
507
+ background: #111;
508
+ }
509
+
510
+ .paper-view-loading {
511
+ display: flex;
512
+ align-items: center;
513
+ justify-content: center;
514
+ min-height: 200px;
515
+ flex-direction: column;
516
+ gap: 16px;
517
+ }
518
+
519
+ .loading-spinner {
520
+ width: 32px;
521
+ height: 32px;
522
+ border: 2px solid var(--border-card);
523
+ border-top-color: var(--accent);
524
+ border-radius: 50%;
525
+ animation: spin 0.8s linear infinite;
526
+ }
527
+
528
+ @keyframes spin {
529
+ to { transform: rotate(360deg); }
530
+ }
531
+
532
+ /* ---- Paper Body (inside modal) ---- */
533
+ .paper-body {
534
+ color: var(--text-soft);
535
+ max-width: 900px;
536
+ margin: 0 auto;
537
+ }
538
+
539
+ .paper-body h1 {
540
+ font-family: 'Geist', sans-serif;
541
+ font-size: 2rem;
542
+ font-weight: 700;
543
+ letter-spacing: -0.03em;
544
+ line-height: 1.2;
545
+ color: var(--text);
546
+ margin-bottom: 8px;
547
+ }
548
+
549
+ .paper-body h2 {
550
+ font-family: 'Geist', sans-serif;
551
+ font-size: 1.3rem;
552
+ font-weight: 600;
553
+ letter-spacing: -0.02em;
554
+ color: var(--text-soft);
555
+ margin: 36px 0 12px;
556
+ padding-bottom: 8px;
557
+ border-bottom: 1px solid var(--border-card);
558
+ }
559
+
560
+ .paper-body h2:first-child {
561
+ margin-top: 0;
562
+ }
563
+
564
+ .paper-body h3 {
565
+ font-family: 'Geist', sans-serif;
566
+ font-size: 1.05rem;
567
+ font-weight: 600;
568
+ color: var(--text-muted);
569
+ margin: 22px 0 8px;
570
+ }
571
+
572
+ .paper-body p {
573
+ margin-bottom: 14px;
574
+ line-height: 1.75;
575
+ }
576
+
577
+ .paper-body ol,
578
+ .paper-body ul {
579
+ margin: 0 0 14px 24px;
580
+ }
581
+
582
+ .paper-body li {
583
+ margin-bottom: 6px;
584
+ }
585
+
586
+ .paper-body strong {
587
+ font-weight: 600;
588
+ color: var(--text);
589
+ }
590
+
591
+ .paper-body em {
592
+ font-style: italic;
593
+ }
594
+
595
+ .paper-body code {
596
+ font-family: 'Geist Mono', monospace;
597
+ font-size: 0.82em;
598
+ background: rgba(255, 255, 255, 0.05);
599
+ padding: 2px 7px;
600
+ border-radius: 4px;
601
+ border: 1px solid var(--border-card);
602
+ color: var(--accent);
603
+ }
604
+
605
+ .paper-body hr {
606
+ border: none;
607
+ border-top: 1px solid var(--border-card);
608
+ margin: 28px 0;
609
+ }
610
+
611
+ .paper-body blockquote {
612
+ border-left: 2px solid var(--accent-muted);
613
+ padding-left: 16px;
614
+ margin: 18px 0;
615
+ color: var(--text-muted);
616
+ font-style: italic;
617
+ }
618
+
619
+ /* ---- Credit section ---- */
620
+ .paper-credit {
621
+ margin-top: 40px;
622
+ padding-top: 20px;
623
+ border-top: 1px solid var(--border-card);
624
+ font-family: 'Geist Mono', monospace;
625
+ font-size: 13px;
626
+ color: var(--text-dim);
627
+ text-align: right;
628
+ letter-spacing: 0.04em;
629
+ }
630
+
631
+ .paper-credit .credit-label {
632
+ font-style: italic;
633
+ }
634
+
635
+ .paper-credit .credit-names {
636
+ font-weight: 500;
637
+ color: var(--text-muted);
638
+ }
639
+
640
+ /* ---- Papermaker callout ---- */
641
+ .papermaker-callout {
642
+ text-align: center;
643
+ padding: 48px 24px 32px;
644
+ max-width: 560px;
645
+ margin: 0 auto;
646
+ }
647
+
648
+ .papermaker-callout p {
649
+ font-family: 'Geist', sans-serif;
650
+ font-size: 14px;
651
+ font-weight: 350;
652
+ line-height: 1.6;
653
+ color: var(--text-dim);
654
+ }
655
+
656
+ .papermaker-callout .role-name {
657
+ font-family: 'Geist Mono', monospace;
658
+ font-weight: 500;
659
+ color: var(--accent-muted);
660
+ }
661
+
662
+ /* ---- Footer ---- */
663
+ .site-footer {
664
+ text-align: center;
665
+ padding: 0 0 64px;
666
+ font-family: 'Geist Mono', monospace;
667
+ font-size: 11px;
668
+ letter-spacing: 0.1em;
669
+ text-transform: uppercase;
670
+ color: var(--text-dim);
671
+ opacity: 0.5;
672
+ }
673
+
674
+ /* ---- Empty State ---- */
675
+ .empty-state {
676
+ text-align: center;
677
+ padding: 80px 24px;
678
+ grid-column: 1 / -1;
679
+ }
680
+
681
+ .empty-state p {
682
+ font-size: 16px;
683
+ color: var(--text-dim);
684
+ font-style: italic;
685
+ }
686
+
687
+ /* ---- Error State ---- */
688
+ .error-banner {
689
+ text-align: center;
690
+ padding: 60px 24px;
691
+ grid-column: 1 / -1;
692
+ }
693
+
694
+ .error-banner p {
695
+ font-family: 'Geist Mono', monospace;
696
+ font-size: 13px;
697
+ color: var(--text-dim);
698
+ }
699
+
700
+ /* ---- Responsive ---- */
701
+ @media (max-width: 640px) {
702
+ .container {
703
+ padding: 0 20px;
704
+ }
705
+
706
+ .site-header {
707
+ padding: 56px 0 36px;
708
+ }
709
+
710
+ .site-title {
711
+ font-size: clamp(36px, 10vw, 56px);
712
+ }
713
+
714
+ .paper-card {
715
+ padding: 22px 24px;
716
+ min-height: 140px;
717
+ }
718
+
719
+ .paper-view {
720
+ padding: 32px 20px;
721
+ min-height: auto;
722
+ }
723
+
724
+ .paper-view-frame {
725
+ min-height: 70vh;
726
+ }
727
+
728
+ .papers-grid {
729
+ gap: 12px;
730
+ }
731
+ }
732
+
733
+ @media print {
734
+ body {
735
+ background: white;
736
+ color: black;
737
+ }
738
+
739
+ body::before,
740
+ body::after {
741
+ display: none;
742
+ }
743
+
744
+ .paper-overlay {
745
+ position: static;
746
+ background: none;
747
+ backdrop-filter: none;
748
+ }
749
+
750
+ .paper-view {
751
+ background: white;
752
+ color: black;
753
+ box-shadow: none;
754
+ border: none;
755
+ min-height: auto;
756
+ padding: 24px 0;
757
+ position: static;
758
+ animation: none;
759
+ }
760
+
761
+ .paper-view-frame {
762
+ min-height: 0;
763
+ height: auto;
764
+ }
765
+
766
+ .paper-view-close {
767
+ display: none;
768
+ }
769
+ }
770
+
771
+
772
+ /* ---- Paper Page Layout ---- */
773
+ .paper-page {
774
+ padding: 64px 0 80px;
775
+ }
776
+
777
+ .paper-page .paper-page-shell {
778
+ max-width: 900px;
779
+ margin: 0 auto;
780
+ }
781
+
782
+ .paper-page .paper-page-title {
783
+ font-family: 'Geist', sans-serif;
784
+ font-size: clamp(34px, 5vw, 56px);
785
+ font-weight: 700;
786
+ letter-spacing: -0.03em;
787
+ line-height: 1.08;
788
+ color: var(--text);
789
+ margin-bottom: 12px;
790
+ }
791
+
792
+ .paper-page .paper-page-meta {
793
+ font-family: 'Geist Mono', monospace;
794
+ font-size: 12px;
795
+ letter-spacing: 0.08em;
796
+ text-transform: uppercase;
797
+ color: var(--text-dim);
798
+ margin-bottom: 36px;
799
+ }
800
+
801
+ .paper-page .paper-page-iframe-note {
802
+ display: none;
803
+ }
index.html CHANGED
@@ -9,759 +9,7 @@
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
  <link href="https://fonts.googleapis.com/css2?family=Geist:wght@300..700&family=Geist+Mono:wght@400;500&display=swap" rel="stylesheet">
11
 
12
- <style>
13
- *,
14
- *::before,
15
- *::after {
16
- margin: 0;
17
- padding: 0;
18
- box-sizing: border-box;
19
- }
20
-
21
- :root {
22
- --bg: #000000;
23
- --bg-card: #0a0a0a;
24
- --bg-card-hover: #0f0f0f;
25
- --border-card: #1a1a1a;
26
- --text: #ffffff;
27
- --text-soft: #f5f5f5;
28
- --text-muted: #888888;
29
- --text-dim: #555555;
30
- --accent: #c8960c;
31
- --accent-bright: #ffd633;
32
- --accent-muted: #8b6508;
33
- --gold-gradient: linear-gradient(135deg, #ffd633 0%, #c8960c 50%, #a0760a 100%);
34
- --grid-line: rgba(255, 255, 255, 0.03);
35
- --grid-line-major: rgba(255, 255, 255, 0.06);
36
- --container-max: none;
37
- }
38
-
39
- html {
40
- scroll-behavior: smooth;
41
- background: var(--bg);
42
- }
43
-
44
- /* ---- Focus styles ---- */
45
- :focus-visible {
46
- outline: 2px solid var(--accent-bright);
47
- outline-offset: 3px;
48
- border-radius: 4px;
49
- }
50
-
51
- .paper-card:focus-visible {
52
- outline: 2px solid var(--accent-bright);
53
- outline-offset: 2px;
54
- border-radius: 12px;
55
- }
56
-
57
- .paper-view-close:focus-visible {
58
- outline: 2px solid var(--accent-bright);
59
- outline-offset: 2px;
60
- border-radius: 8px;
61
- }
62
-
63
- /* ---- Skip link ---- */
64
- .skip-link {
65
- position: fixed;
66
- top: 0;
67
- left: 0;
68
- z-index: 200;
69
- padding: 12px 20px;
70
- background: var(--accent);
71
- color: #000;
72
- font-family: 'Geist', sans-serif;
73
- font-size: 14px;
74
- font-weight: 600;
75
- text-decoration: none;
76
- border-radius: 0 0 8px 0;
77
- transform: translateY(-100%);
78
- transition: transform 0.15s ease;
79
- }
80
-
81
- .skip-link:focus {
82
- transform: translateY(0);
83
- }
84
-
85
- /* ---- Screen reader only ---- */
86
- .sr-only {
87
- position: absolute;
88
- width: 1px;
89
- height: 1px;
90
- padding: 0;
91
- margin: -1px;
92
- overflow: hidden;
93
- clip: rect(0, 0, 0, 0);
94
- white-space: nowrap;
95
- border: 0;
96
- }
97
-
98
- /* ---- Reduced motion ---- */
99
- @media (prefers-reduced-motion: reduce) {
100
- *,
101
- *::before,
102
- *::after {
103
- animation-duration: 0.01ms !important;
104
- animation-iteration-count: 1 !important;
105
- transition-duration: 0.01ms !important;
106
- }
107
-
108
- html {
109
- scroll-behavior: auto;
110
- }
111
- }
112
-
113
- body {
114
- background: var(--bg);
115
- color: var(--text);
116
- font-family: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
117
- font-size: 16px;
118
- font-weight: 350;
119
- line-height: 1.7;
120
- min-height: 100vh;
121
- position: relative;
122
- overflow-x: hidden;
123
- }
124
-
125
- /* ---- Dot grid background ---- */
126
- body::before {
127
- content: '';
128
- position: fixed;
129
- inset: 0;
130
- pointer-events: none;
131
- z-index: 0;
132
- background-image:
133
- radial-gradient(circle, var(--grid-line) 1px, transparent 1px);
134
- background-size: 40px 40px;
135
- mask-image: radial-gradient(ellipse 70% 70% at 50% 0%, black 30%, transparent 70%);
136
- -webkit-mask-image: radial-gradient(ellipse 70% 70% at 50% 0%, black 30%, transparent 70%);
137
- }
138
-
139
- body::after {
140
- content: '';
141
- position: fixed;
142
- inset: 0;
143
- pointer-events: none;
144
- z-index: 0;
145
- background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.02'/%3E%3C/svg%3E");
146
- opacity: 0.4;
147
- }
148
-
149
- /* ---- Container ---- */
150
- .container {
151
- position: relative;
152
- z-index: 1;
153
- max-width: var(--container-max);
154
- margin: 0 auto;
155
- padding: 0 40px;
156
- }
157
-
158
- /* ---- Header ---- */
159
- .site-header {
160
- padding: 80px 0 48px;
161
- text-align: center;
162
- position: relative;
163
- }
164
-
165
- .site-title {
166
- font-family: 'Geist', sans-serif;
167
- font-size: clamp(48px, 8vw, 80px);
168
- font-weight: 700;
169
- letter-spacing: -0.03em;
170
- line-height: 1.05;
171
- color: var(--text);
172
- animation: fadeUp 0.8s ease-out both;
173
- }
174
-
175
- .site-title .gold {
176
- background: var(--gold-gradient);
177
- -webkit-background-clip: text;
178
- -webkit-text-fill-color: transparent;
179
- background-clip: text;
180
- }
181
-
182
- .site-subtitle {
183
- font-family: 'Geist Mono', monospace;
184
- font-size: 13px;
185
- font-weight: 400;
186
- letter-spacing: 0.12em;
187
- text-transform: uppercase;
188
- color: var(--text-dim);
189
- margin-top: 16px;
190
- animation: fadeUp 0.8s 0.15s ease-out both;
191
- }
192
-
193
- .header-divider {
194
- width: 60px;
195
- height: 1px;
196
- background: var(--gold-gradient);
197
- margin: 32px auto 0;
198
- opacity: 0.5;
199
- animation: fadeUp 0.8s 0.2s ease-out both;
200
- }
201
-
202
- @keyframes fadeUp {
203
- from { opacity: 0; transform: translateY(20px); }
204
- to { opacity: 1; transform: translateY(0); }
205
- }
206
-
207
- /* ---- Section label ---- */
208
- .section-label {
209
- font-family: 'Geist Mono', monospace;
210
- font-size: 11px;
211
- font-weight: 500;
212
- letter-spacing: 0.14em;
213
- text-transform: uppercase;
214
- color: var(--text-dim);
215
- margin-bottom: 24px;
216
- padding-left: 2px;
217
- }
218
-
219
- /* ---- Paper Grid ---- */
220
- .papers-grid {
221
- display: grid;
222
- grid-template-columns: repeat(3, 1fr);
223
- gap: 28px;
224
- padding-bottom: 96px;
225
- list-style: none;
226
- }
227
-
228
- @media (max-width: 1100px) {
229
- .papers-grid {
230
- grid-template-columns: repeat(2, 1fr);
231
- }
232
- }
233
-
234
- @media (max-width: 600px) {
235
- .papers-grid {
236
- grid-template-columns: 1fr;
237
- }
238
- }
239
-
240
- /* ---- Paper Card (catalog) ---- */
241
- .paper-card {
242
- position: relative;
243
- background: var(--bg-card);
244
- border: 1px solid var(--border-card);
245
- border-radius: 12px;
246
- padding: 32px 36px;
247
- cursor: pointer;
248
- min-height: 180px;
249
- display: flex;
250
- flex-direction: column;
251
- justify-content: space-between;
252
- transition: all 0.35s ease;
253
- overflow: hidden;
254
- animation: fadeUp 0.6s ease-out both;
255
- }
256
-
257
- .paper-card::before {
258
- content: '';
259
- position: absolute;
260
- inset: 0;
261
- border-radius: 12px;
262
- background: radial-gradient(
263
- 600px circle at var(--mx, 50%) var(--my, 50%),
264
- rgba(200, 150, 12, 0.06),
265
- transparent 40%
266
- );
267
- opacity: 0;
268
- transition: opacity 0.4s ease;
269
- pointer-events: none;
270
- }
271
-
272
- .paper-card:hover {
273
- border-color: rgba(200, 150, 12, 0.3);
274
- background: var(--bg-card-hover);
275
- transform: translateY(-2px);
276
- box-shadow:
277
- 0 20px 60px rgba(0, 0, 0, 0.4),
278
- 0 0 0 1px rgba(200, 150, 12, 0.08);
279
- }
280
-
281
- .paper-card:hover::before {
282
- opacity: 1;
283
- }
284
-
285
- .paper-card:active {
286
- transform: translateY(0);
287
- transition: all 0.1s ease;
288
- }
289
-
290
- .card-title {
291
- font-family: 'Geist', sans-serif;
292
- font-size: 20px;
293
- font-weight: 600;
294
- letter-spacing: -0.02em;
295
- line-height: 1.3;
296
- color: var(--text);
297
- margin-bottom: 10px;
298
- }
299
-
300
- .card-author {
301
- font-family: 'Geist Mono', monospace;
302
- font-size: 11px;
303
- font-weight: 500;
304
- letter-spacing: 0.06em;
305
- color: var(--accent-muted);
306
- margin-bottom: 8px;
307
- }
308
-
309
- .card-meta {
310
- display: flex;
311
- align-items: center;
312
- gap: 12px;
313
- font-family: 'Geist Mono', monospace;
314
- font-size: 12px;
315
- color: var(--text-dim);
316
- }
317
-
318
- .card-tag {
319
- font-family: 'Geist Mono', monospace;
320
- font-size: 10px;
321
- font-weight: 500;
322
- letter-spacing: 0.08em;
323
- text-transform: uppercase;
324
- color: var(--accent-muted);
325
- background: rgba(200, 150, 12, 0.08);
326
- padding: 3px 8px;
327
- border-radius: 4px;
328
- border: 1px solid rgba(200, 150, 12, 0.12);
329
- }
330
-
331
- .card-proved {
332
- font-family: 'Geist Mono', monospace;
333
- font-size: 10px;
334
- font-weight: 600;
335
- letter-spacing: 0.08em;
336
- text-transform: uppercase;
337
- color: #1a7a1a;
338
- background: rgba(26, 122, 26, 0.1);
339
- padding: 3px 10px;
340
- border-radius: 4px;
341
- border: 1px solid rgba(26, 122, 26, 0.2);
342
- flex-shrink: 0;
343
- }
344
-
345
- /* ---- Featured card ---- */
346
- .paper-card.featured {
347
- grid-column: 1 / -1;
348
- padding: 48px 56px;
349
- min-height: 220px;
350
- border-color: color-mix(in srgb, var(--accent) 25%, transparent);
351
- background: radial-gradient(ellipse 70% 50% at 50% 0%, rgba(200, 150, 12, 0.04), transparent 60%), var(--bg-card);
352
- }
353
-
354
- .paper-card.featured .card-title {
355
- font-size: 28px;
356
- letter-spacing: -0.03em;
357
- }
358
-
359
- .paper-card.featured .card-author {
360
- font-size: 12px;
361
- margin-bottom: 12px;
362
- }
363
-
364
- .paper-card.featured .card-meta {
365
- font-size: 13px;
366
- }
367
-
368
- .paper-card.featured:hover {
369
- border-color: color-mix(in srgb, var(--accent) 45%, transparent);
370
- background: radial-gradient(ellipse 70% 50% at 50% 0%, rgba(200, 150, 12, 0.07), transparent 60%), var(--bg-card-hover);
371
- }
372
-
373
- @media (max-width: 640px) {
374
- .paper-card.featured {
375
- padding: 28px 24px;
376
- min-height: 160px;
377
- }
378
-
379
- .paper-card.featured .card-title {
380
- font-size: 22px;
381
- }
382
- }
383
-
384
- /* ---- Proof script in paper view ---- */
385
- .proof-section {
386
- margin-top: 32px;
387
- padding-top: 24px;
388
- border-top: 1px solid var(--border-card);
389
- }
390
-
391
- .proof-label {
392
- font-family: 'Geist Mono', monospace;
393
- font-size: 11px;
394
- font-weight: 600;
395
- letter-spacing: 0.1em;
396
- text-transform: uppercase;
397
- color: #1a7a1a;
398
- margin-bottom: 14px;
399
- }
400
-
401
- .proof-script {
402
- background: rgba(0, 0, 0, 0.4);
403
- border: 1px solid var(--border-card);
404
- border-radius: 8px;
405
- padding: 20px 24px;
406
- overflow-x: auto;
407
- font-family: 'Geist Mono', monospace;
408
- font-size: 12px;
409
- line-height: 1.6;
410
- color: var(--text-muted);
411
- tab-size: 4;
412
- max-height: 500px;
413
- overflow-y: auto;
414
- }
415
-
416
- .proof-script::-webkit-scrollbar {
417
- width: 6px;
418
- height: 6px;
419
- }
420
-
421
- .proof-script::-webkit-scrollbar-track {
422
- background: transparent;
423
- }
424
-
425
- .proof-script::-webkit-scrollbar-thumb {
426
- background: var(--border-card);
427
- border-radius: 3px;
428
- }
429
-
430
- .card-arrow {
431
- position: absolute;
432
- right: 24px;
433
- top: 50%;
434
- transform: translateY(-50%);
435
- font-size: 20px;
436
- color: var(--text-dim);
437
- opacity: 0;
438
- transition: all 0.3s ease;
439
- }
440
-
441
- .paper-card:hover .card-arrow {
442
- opacity: 1;
443
- color: var(--accent);
444
- }
445
-
446
- /* ---- Modal / Paper View ---- */
447
- .paper-overlay {
448
- position: fixed;
449
- inset: 0;
450
- z-index: 100;
451
- background: rgba(0, 0, 0, 0.9);
452
- backdrop-filter: blur(12px);
453
- -webkit-backdrop-filter: blur(12px);
454
- display: flex;
455
- align-items: flex-start;
456
- justify-content: center;
457
- padding: 0;
458
- overflow-y: auto;
459
- animation: overlayIn 0.25s ease-out;
460
- }
461
-
462
- @keyframes overlayIn {
463
- from { opacity: 0; }
464
- to { opacity: 1; }
465
- }
466
-
467
- .paper-view {
468
- background: #0d0d0d;
469
- border: none;
470
- border-radius: 0;
471
- max-width: none;
472
- width: 100%;
473
- min-height: 100vh;
474
- padding: 64px clamp(32px, 8vw, 120px) 80px;
475
- position: relative;
476
- animation: modalIn 0.35s ease-out;
477
- box-shadow: none;
478
- }
479
-
480
- @keyframes modalIn {
481
- from { opacity: 0; transform: translateY(24px) scale(0.97); }
482
- to { opacity: 1; transform: translateY(0) scale(1); }
483
- }
484
-
485
- .paper-view-close {
486
- position: fixed;
487
- top: 24px;
488
- right: 24px;
489
- width: 40px;
490
- height: 40px;
491
- border-radius: 8px;
492
- border: 1px solid var(--border-card);
493
- background: rgba(10, 10, 10, 0.9);
494
- backdrop-filter: blur(8px);
495
- -webkit-backdrop-filter: blur(8px);
496
- color: var(--text-muted);
497
- cursor: pointer;
498
- display: flex;
499
- align-items: center;
500
- justify-content: center;
501
- font-size: 20px;
502
- font-family: 'Geist Mono', monospace;
503
- transition: all 0.2s ease;
504
- z-index: 10;
505
- }
506
-
507
- .paper-view-close:hover {
508
- border-color: rgba(200, 150, 12, 0.4);
509
- color: var(--accent);
510
- background: #111;
511
- }
512
-
513
- .paper-view-loading {
514
- display: flex;
515
- align-items: center;
516
- justify-content: center;
517
- min-height: 200px;
518
- flex-direction: column;
519
- gap: 16px;
520
- }
521
-
522
- .loading-spinner {
523
- width: 32px;
524
- height: 32px;
525
- border: 2px solid var(--border-card);
526
- border-top-color: var(--accent);
527
- border-radius: 50%;
528
- animation: spin 0.8s linear infinite;
529
- }
530
-
531
- @keyframes spin {
532
- to { transform: rotate(360deg); }
533
- }
534
-
535
- /* ---- Paper Body (inside modal) ---- */
536
- .paper-body {
537
- color: var(--text-soft);
538
- max-width: 900px;
539
- margin: 0 auto;
540
- }
541
-
542
- .paper-body h1 {
543
- font-family: 'Geist', sans-serif;
544
- font-size: 2rem;
545
- font-weight: 700;
546
- letter-spacing: -0.03em;
547
- line-height: 1.2;
548
- color: var(--text);
549
- margin-bottom: 8px;
550
- }
551
-
552
- .paper-body h2 {
553
- font-family: 'Geist', sans-serif;
554
- font-size: 1.3rem;
555
- font-weight: 600;
556
- letter-spacing: -0.02em;
557
- color: var(--text-soft);
558
- margin: 36px 0 12px;
559
- padding-bottom: 8px;
560
- border-bottom: 1px solid var(--border-card);
561
- }
562
-
563
- .paper-body h2:first-child {
564
- margin-top: 0;
565
- }
566
-
567
- .paper-body h3 {
568
- font-family: 'Geist', sans-serif;
569
- font-size: 1.05rem;
570
- font-weight: 600;
571
- color: var(--text-muted);
572
- margin: 22px 0 8px;
573
- }
574
-
575
- .paper-body p {
576
- margin-bottom: 14px;
577
- line-height: 1.75;
578
- }
579
-
580
- .paper-body ol,
581
- .paper-body ul {
582
- margin: 0 0 14px 24px;
583
- }
584
-
585
- .paper-body li {
586
- margin-bottom: 6px;
587
- }
588
-
589
- .paper-body strong {
590
- font-weight: 600;
591
- color: var(--text);
592
- }
593
-
594
- .paper-body em {
595
- font-style: italic;
596
- }
597
-
598
- .paper-body code {
599
- font-family: 'Geist Mono', monospace;
600
- font-size: 0.82em;
601
- background: rgba(255, 255, 255, 0.05);
602
- padding: 2px 7px;
603
- border-radius: 4px;
604
- border: 1px solid var(--border-card);
605
- color: var(--accent);
606
- }
607
-
608
- .paper-body hr {
609
- border: none;
610
- border-top: 1px solid var(--border-card);
611
- margin: 28px 0;
612
- }
613
-
614
- .paper-body blockquote {
615
- border-left: 2px solid var(--accent-muted);
616
- padding-left: 16px;
617
- margin: 18px 0;
618
- color: var(--text-muted);
619
- font-style: italic;
620
- }
621
-
622
- /* ---- Credit section ---- */
623
- .paper-credit {
624
- margin-top: 40px;
625
- padding-top: 20px;
626
- border-top: 1px solid var(--border-card);
627
- font-family: 'Geist Mono', monospace;
628
- font-size: 13px;
629
- color: var(--text-dim);
630
- text-align: right;
631
- letter-spacing: 0.04em;
632
- }
633
-
634
- .paper-credit .credit-label {
635
- font-style: italic;
636
- }
637
-
638
- .paper-credit .credit-names {
639
- font-weight: 500;
640
- color: var(--text-muted);
641
- }
642
-
643
- /* ---- Papermaker callout ---- */
644
- .papermaker-callout {
645
- text-align: center;
646
- padding: 48px 24px 32px;
647
- max-width: 560px;
648
- margin: 0 auto;
649
- }
650
-
651
- .papermaker-callout p {
652
- font-family: 'Geist', sans-serif;
653
- font-size: 14px;
654
- font-weight: 350;
655
- line-height: 1.6;
656
- color: var(--text-dim);
657
- }
658
-
659
- .papermaker-callout .role-name {
660
- font-family: 'Geist Mono', monospace;
661
- font-weight: 500;
662
- color: var(--accent-muted);
663
- }
664
-
665
- /* ---- Footer ---- */
666
- .site-footer {
667
- text-align: center;
668
- padding: 0 0 64px;
669
- font-family: 'Geist Mono', monospace;
670
- font-size: 11px;
671
- letter-spacing: 0.1em;
672
- text-transform: uppercase;
673
- color: var(--text-dim);
674
- opacity: 0.5;
675
- }
676
-
677
- /* ---- Empty State ---- */
678
- .empty-state {
679
- text-align: center;
680
- padding: 80px 24px;
681
- grid-column: 1 / -1;
682
- }
683
-
684
- .empty-state p {
685
- font-size: 16px;
686
- color: var(--text-dim);
687
- font-style: italic;
688
- }
689
-
690
- /* ---- Error State ---- */
691
- .error-banner {
692
- text-align: center;
693
- padding: 60px 24px;
694
- grid-column: 1 / -1;
695
- }
696
-
697
- .error-banner p {
698
- font-family: 'Geist Mono', monospace;
699
- font-size: 13px;
700
- color: var(--text-dim);
701
- }
702
-
703
- /* ---- Responsive ---- */
704
- @media (max-width: 640px) {
705
- .container {
706
- padding: 0 20px;
707
- }
708
-
709
- .site-header {
710
- padding: 56px 0 36px;
711
- }
712
-
713
- .site-title {
714
- font-size: clamp(36px, 10vw, 56px);
715
- }
716
-
717
- .paper-card {
718
- padding: 22px 24px;
719
- min-height: 140px;
720
- }
721
-
722
- .paper-view {
723
- padding: 32px 20px;
724
- min-height: auto;
725
- }
726
-
727
- .papers-grid {
728
- gap: 12px;
729
- }
730
- }
731
-
732
- @media print {
733
- body {
734
- background: white;
735
- color: black;
736
- }
737
-
738
- body::before,
739
- body::after {
740
- display: none;
741
- }
742
-
743
- .paper-overlay {
744
- position: static;
745
- background: none;
746
- backdrop-filter: none;
747
- }
748
-
749
- .paper-view {
750
- background: white;
751
- color: black;
752
- box-shadow: none;
753
- border: none;
754
- min-height: auto;
755
- padding: 24px 0;
756
- position: static;
757
- animation: none;
758
- }
759
-
760
- .paper-view-close {
761
- display: none;
762
- }
763
- }
764
- </style>
765
  </head>
766
  <body>
767
 
@@ -792,549 +40,6 @@
792
  </div>
793
  </footer>
794
 
795
- <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
796
-
797
-
798
- <script type="text/markdown" id="paper-trueact-md"># TrueACT: A Different Kind of Neuron
799
-
800
- Transformers use the same MLP on every token. Every time. Same weights, same math, no memory of where it's been in the sequence, no sense of how confident it is. TrueACT chucks that. Replaces the MLP with a small recurrent block that loops. Reads the token, updates a hidden state, checks if it's confident enough, either answers or loops again. Keeps going til it hits 0.99 confidence or runs out of steps.
801
-
802
- It's not a standard neuron. It's not an attention head. It's a loop with a router that picks between four specialized operations depending on what the token needs.
803
-
804
- Half the parameters of the equivalent standard model. Same loss. 2.8x slower cause of the loop. You're trading flops for parameter efficiency.
805
-
806
- ## the four experts
807
-
808
- Each TrueACT layer has four experts. The router picks which combination to use per token, not per layer. So different tokens in the same batch can fire different experts. Here's what they do:
809
-
810
- **Think Cell** — this is the actual recurrent part. Updates the latent state, which is basically working memory that persists across steps within the same layer. Think of it like scratch paper the model scribbles on while reasoning.
811
-
812
- **Standard** — plain linear pattern matching. Same job the normal MLP would do. Catches the easy stuff.
813
-
814
- **Fancy** — this is the weird one. Does math in log-space. For multiplication, `log(a*b) = log(a) + log(b)`. Addition is something a linear layer can already do. So instead of needing a pile of neurons to approximate a multiplication curve, one Fancy expert can do it cleanly. Log then add then exp. Multiplication, division, ratios, chained operations.
815
-
816
- **Memory Vault** — key → value associative lookup. A dedicated place to store facts instead of smearing them across all the weights. Retrieve, don't approximate.
817
-
818
- The router takes `[input, latent_state, step_count]`, sticks it through a linear layer plus softmax, and that's the expert selection. Standard and Fancy spend from an action budget. Once the budget is gone, the loop stops, unless it hits the 32-step cap.
819
-
820
- ## why this works
821
-
822
- A standard transformer neuron is a linear approximator. For something like `a * b = c`, you'd need a big pile of neurons approximating a curve. It works eventually but it's wasteful. The weights end up encoding the same multiplication table across hundreds of parameters, and there's no clean way to just *do the math*.
823
-
824
- The Fancy expert sidesteps that. Goes to log-space, adds, comes back. One neuron doing what used to take a crowd.
825
-
826
- The Memory Vault is the same idea from the other direction. Instead of memorizing facts by storing them implicitly in weight matrices, just do a key-value lookup. Store it once, retrieve it when needed.
827
-
828
- The Think Cell ties it together. Gives the model a place to hold intermediate state while it loops through the experts. Without it, each token is a one-shot guess. With it, the model can go "hmm let me think about this" and take another step.
829
-
830
- So the model gets more mileage per parameter. The tradeoff is sequential compute. You can't parallelize a loop that depends on its own output. That's where the 2.8x slowdown comes from.
831
-
832
- ## the numbers
833
-
834
- 3-layer LLaMA-style comparison at d=384:
835
-
836
- | metric | Standard | TrueACT |
837
- |---|---|---|
838
- | loss | 0.0884 | 0.0880 |
839
- | params | 852,864 | 428,652 |
840
- | train speed | 1x | 2.8x slower |
841
-
842
- Same loss, roughly half the weights. The slowdown is real — the loop is sequential, can't be parallelized. But you're getting the same quality out of half the parameter budget.
843
-
844
- 1-layer arithmetic reasoner: 12/12 on a fixed 12-expression benchmark. 91.6% on 500 random expressions. The misses are mostly multi-digit arithmetic — `42*88=3524` type stuff. Structure like parentheses, operator precedence, intermediate steps — those come out clean. The model actually writes out the worked steps: `((5*5)+(10*2))=(25+(10*2))=(25+20)=45|`
845
-
846
- ## the router in action
847
-
848
- The routing stats tell you what the model's doing under the hood. Example from the inference CLI:
849
-
850
- ```
851
- Prompt > ((5*5)+(10*2))=
852
- TrueACT : ((5*5)+(10*2))=(25+(10*2))=(25+20)=45|
853
- [Think: 15% | Stand: 30% | Fancy: 45% | Vault: 10%]
854
- ```
855
-
856
- For arithmetic, Fancy gets most of the budget. Makes sense — multiplication is the expensive operation and Fancy handles it in log-space. Standard catches the easy pattern matching (digits, parens, equals signs). Think Cell does the state tracking across steps. Memory Vault probably handles the number facts.
857
-
858
- The router isn't pre-programmed. It learns which expert to use for which kind of token during training. The routing stats are emergent.
859
-
860
- ## how training works
861
-
862
- Data is an infinite stream of generated arithmetic — `+`, `-`, `*`, parentheses, multi-step chains. Format is `((5*5)+(10*2))=(25+(10*2))=(25+20)=45|`. The model sees a random position in the chain and has to predict the next character.
863
-
864
- Context window is 64 chars, one-hot encoded. The alphabet is 12 characters (digits, operators, parens, equals, pipe) so the input is 768-dimensional one-hots.
865
-
866
- Batch size 8192. AdamW, lr 5e-4, weight decay 0.01. 1-3 layer TrueACTStack, t_dim=256, max 32 ACT steps per layer.
867
-
868
- Training also runs a StandardStack (same structure, ordinary SiLU MLPs) side by side as the control group. Checkpoints save both every 500 steps.
869
-
870
- ## the architecture, deeper
871
-
872
- **TrueACTLayer**: concat input x and latent h → xh. Router reads `[xh, step_frac]` → softmax over 4 experts. Compute expert outputs, gate by `router_prob * remaining_budget`, accumulate into the result, update h through the Think Cell. Repeat til budget hits zero or 32 steps.
873
-
874
- **TrueACTStack**: N of those layers with residual connections. Input projection to model dim at the bottom, output projection to vocab at the top.
875
-
876
- **StandardStack**: same structure but with normal SiLU MLPs instead of the TrueACT loop. The control group.
877
-
878
- The budget mechanism matters. Standard and Fancy both consume budget when used. Think Cell and Memory Vault, from how they're structured, seem to be state management rather than compute, so they don't appear to draw from the budget. The model can think (Think Cell) and retrieve (Memory Vault) freely. Only the expensive ops cost steps.
879
-
880
- ## how it started
881
-
882
- This thing began as one log-space neuron trying to learn `x*y=z`. That's it. One neuron doing multiplication in log-space.
883
-
884
- 41 notes later in MEMORY.md. Mode collapse. Gradient explosions. Dead architecture after dead architecture. Full rewrites. Things that almost worked before falling apart at higher dimensions.
885
-
886
- The 41 notes on what didn't work are arguably more valuable than what did. Every dead end, every fix, every "wait that shouldn't have helped" moment. Built for AI agents to read so they don't repeat the same mistakes.
887
-
888
- The four-expert router, the Think Cell, the budget gating, the step cap — none of that was in the original idea. Each piece got added because something broke without it.
889
-
890
- ## looking forward
891
-
892
- The toy results are promising. Half the params, same loss. The next step is figuring out if this scales past small arithmetic models, and what the loop overhead looks like at bigger sizes. That's the open question.
893
-
894
- ---
895
-
896
- *the 41st attempt finally worked. go read MEMORY.md if you wanna avoid the first 40.*
897
-
898
- ## tldr
899
-
900
- - Swap the transformer MLP for a recurrent block that loops til it's confident
901
- - Four experts: Think Cell (working memory), Standard (linear matching), Fancy (log-space math), Memory Vault (key→value lookup)
902
- - Router picks which experts fire per token based on input, latent state, and step count
903
- - Half the params (429k vs 853k), same loss (0.0880 vs 0.0884), 2.8x slower
904
- - 1-layer solves 12/12 on fixed benchmark, 91.6% on 500 random arithmetic expressions
905
- - Fancy expert does `log(a*b) = log(a)+log(b)` — one neuron doing what used to take a crowd
906
- - Started as one log-space neuron, 41 failed notes later it's a whole architecture
907
- - Tradeoff: sequential compute for parameter efficiency
908
-
909
- ---
910
-
911
- *the 41st attempt finally worked. go read MEMORY.md if you wanna avoid the first 40.*
912
-
913
- Credit goes to CompactAI
914
- </script>
915
- <script type="text/markdown" id="paper-STM_paper-md"># STM and the Circle Thing
916
-
917
- STM stands for Subtractive Training Method. Dragonoid threw it out in #general and the chat's been daring each other to "do STM" on a checkpoint ever since. The idea's almost annoyingly simple once you hear it.
918
-
919
- Normally you train a model by shoving the whole dataset at it for an epoch, loss drops, do it again. STM says nah. After that first pass, look at which samples caused the biggest sudden drops in loss, and yank those out. Keep the rest. Train again. Repeat.
920
-
921
- The reasoning: a sample that produces a huge plummet in loss is the model going "oh yeah got that one." Any more gradient steps on that sample after that point is mostly memorization, the model's just carving that exact example deeper into its weights, not learning anything generalizable. Waste of compute. The samples where loss comes down slow and gradual, those are the ones where the model's actually figuring things out. That's generalization. So you let it keep chewing.
922
-
923
- End result: shrinking dataset every epoch. Easy stuff drops away, what's left is the stuff the model still has to actually think about.
924
-
925
- Somebody in the thread asked "so generalization happens with STM?" And yeah, that's the bet. Starve the model of samples it'd otherwise overfit to. Bias toward generalization.
926
-
927
- People noted this isn't quite hard-example mining or curriculum learning, even though it rhymes with em. Curriculum learning usually adds harder stuff over time. STM never adds. Only removes. Dataset shrinks monotonically. You start with everything and trim down to the residue. The "curriculum" isn't scheduled, it emerges from whatever the model still finds hard.
928
-
929
- Also, and this confuses people, the criterion isn't "loss is currently high on this sample." It's "loss DROPPED a lot on this sample." Derivative thing, not level thing. Sample can have low absolute loss and still be worth training on if its loss has been decreasing gradually. Sample with high loss but a sudden crash? Gone. Cut.
930
-
931
- ## the other circle thing (Apollonian gasket, different idea, don't mix em up)
932
-
933
- Same channel's been throwing around a totally separate circles thing. Storing token embeddings as addresses inside an integer Apollonian gasket, keyed by prime tuples from a twin-prime engine. Token maps to a circle, twin primes become semantic neighbors "for free" cause the +2 gap is the local Apollonian step. Weight matrix becomes the curvature graph. Inference is bounded curvature recall, truncate by curvature, filter by primality, verify Descartes-consistency.
934
-
935
- This is NOT the same circle STM talks about. The gasket is embedding storage. Circling is a data-selection pass during training. In principle you could combine em, Mage mused "that might be where my gasket fits", but they're different proposals from different people solving different problems. If you hear "circle" without context, ask which one.
936
-
937
- ## how you'd test this (well, how you WOULD have)
938
-
939
- The obvious experiment, back when it was theoretical:
940
-
941
- 1. Pretrain a small model to some checkpoint
942
- 2. Fork, one copy keeps normal training, other starts STM
943
- 3. Compare validation loss after equal compute, not equal epochs (STM epochs get cheaper as the set shrinks)
944
-
945
- If STM wins it should generalize better and overfit less. If it loses, most likely the easy samples were carrying signal the model still needed and dropping em caused forgetting.
946
-
947
- Somebody also suggested doing STM on pretraining then normal finetuning on top. Makes sense, don't subtract during a phase where you're already dataset-starved.
948
-
949
- ## update: proven
950
-
951
- The STM theory is now fully proven with the final script. Key finding: STM saves training compute and focuses the model on hard data. How much compute you save depends on the mastery floor setting, turns out that matters a lot.
952
-
953
- There was a bug in the original idea, the "Premature Ejection" problem. The naive rule was "drop if loss drops a lot" which sometimes tossed hard samples before the model had really gotten a grip, just cause their loss dipped that epoch. The fix turns the logic into a filter with a safety valve:
954
-
955
- - **Original Rule:** Drop if loss drops a lot.
956
- - **Modified Rule:** Drop if loss drops a lot AND the model has actually reached a mastery floor.
957
-
958
- How to read the results:
959
-
960
- - **Efficiency (3.52x):** By epoch 25, STM had processed 3.5 times fewer tokens than standard training. Each epoch gets cheaper as the dataset shrinks.
961
- - **Pool shift:** Started with 1,000 easy questions and 250 hard ones. By the end, only 6 easy questions remained while 94% of the hard questions survived in the pool. The model cleared easy addition in the first few minutes, then spent 25 epochs grinding hard math.
962
- - **Compute saved (71.6%):** This number came from an early run with mastery floor at 0.15, which turns out to be too aggressive. The dataset shrinks monotonically, each epoch costs less than the last. With a properly tuned floor the per-round savings are lower (1.8% for one round, 21.2% by three rounds), but the point holds: same or better learning, less work.
963
-
964
- The Circle Thing turns out to be a dynamic curriculum generator. The model effectively circles the easy samples and tosses them, ensuring that every gradient step in the later epochs is high-value, high-difficulty work.
965
-
966
- Final verdict: the theory works, it's efficient, and with the Mastery Floor addition it's stable enough for production use. The intuition that STM should focus on hard questions was exactly right. `stm_proof.py` is included, small model on simple addition, point is just to show the mechanism works.
967
-
968
- ## update: recursive STM (Dragonoid's perfection round idea)
969
-
970
- So the single-pass STM worked. But Dragonoid pointed out something nobody'd thought of yet. Once the dataset's been fully STM'd, what if you just. Do it again. Reset the dataset, feed it back in, run STM on top of the already-STM'd checkpoint.
971
-
972
- CompactAI ran it. Two phases, same dataset, same model, just reset the pool between phases.
973
-
974
- Phase 1: model crawled to 45% accuracy, discarded most easy samples along the way. Standard STM behavior.
975
-
976
- Then they reset. Brought every sample back. Fed it to the same model that had just spent 25 epochs grinding exclusively on hard math.
977
-
978
- Phase 2 went different.
979
-
980
- First epoch: accuracy jumped from 45% to 68.5%. Instant. One epoch.
981
-
982
- Second epoch: the model looked at the dataset and went "nah I already know most of this" and yeeted 577 samples right there. Nearly half the pool. The Re-Circle event.
983
-
984
- By the end of Phase 2: 89.5% accuracy. Double what Phase 1 managed.
985
-
986
- So why'd this happen. Dragonoid called it the Recruitment effect.
987
-
988
- Phase 1 the model used easy data to build its foundations. Learned what numbers are, how addition works at a basic level. Then STM yanked the easy stuff and forced the model to grind on hard math for a long time. Those weights shifted. The model developed a more sophisticated grip on arithmetic cause it had to. That's the hard-data focus.
989
-
990
- Then Phase 2 hits. The easy data comes back. But the model's not the same model anymore. Its weights have been reshaped by all that hard-math grinding. So when it sees "3+7=10" again it's like oh. I understand this at a way deeper level now. Solves it with much higher precision. And because its understanding is better, the Re-Circle kicks in at a tighter threshold. Samples that were borderline in Phase 1 get confidently tossed in Phase 2 cause the model's mastery floor is higher now.
991
-
992
- Dragonoid's terminology for this: a cycle is one full STM pass, three phases (not gonna list em here, ask if you care). A round is N cycles. You keep doing cycles until the dataset is fully STM'd, that's one round. Then you reset and go again with a tighter mastery threshold.
993
-
994
- Each round distills the knowledge deeper into the weights. The model isn't just learning the data anymore, it's learning to learn the data better on the second pass.
995
-
996
- The practical takeaway: don't run STM once and call it done. Run it, reset, tighten the bar, run it again. Two rounds got 89.5% on a tiny GRU doing addition. More rounds on bigger models, who knows.
997
-
998
- Dragonoid said "try third round hehehehehe" so CompactAI did. Here's what happens when you push to three generations, measuring unseen hard accuracy at epoch 20 of each round:
999
-
1000
- - Gen 1: 9.2%
1001
- - Gen 2: 29.6%
1002
- - Gen 3: 30.8%
1003
-
1004
- So 3.2x jump from Gen 1 to 2, then only 1.2x from 2 to 3. Diminishing returns, but not terrible. The model's still squeezing a little more out of the data on that third pass. It's not nothing.
1005
-
1006
- Compute savings tell a different story though. After fixing the mastery floor (the early 71.6% run had it cranked to 0.15, way too high), the actual numbers across rounds:
1007
-
1008
- - One round: 1.8% saved
1009
- - Two rounds: 4.0% saved
1010
- - Three rounds: 21.2% saved
1011
-
1012
- Savings compound. The first round barely shrinks anything, the model's being conservative about what it tosses. By round three the model's confident enough to yeet a fifth of the dataset. The floor's doing its job.
1013
-
1014
- The pattern's pretty clear at this point. First reset gives you a huge leap cause the model's weights have been fundamentally changed by the hard-data grinding. Second reset gives a smaller bump, the model's already close to its ceiling on this dataset.
1015
-
1016
- ## tldr
1017
-
1018
- - STM: each epoch, chuck the samples whose loss dropped the most. Train on what's left. Repeat.
1019
- - Circling: the eval pass that figures out what to chuck
1020
- - Big sudden drops = model already memorized it, further training's wasteful. Slow drops = still learning, keep those
1021
- - Proven single-pass: 3.52x efficiency. Compute savings depend on mastery floor (71.6% with floor at 0.15, lower with saner settings). Script included.
1022
- - Recursive STM (Dragonoid): reset dataset after full STM, do it again. Two rounds hit 89.5%, three rounds pushed unseen hard accuracy 9.2% → 29.6% → 30.8%. Compute savings compound: 1.8% → 4.0% → 21.2%.
1023
- - Apollonian gasket circle thing is unrelated. Ask before you mix em up.
1024
-
1025
- ---
1026
-
1027
- *notes from the #general chat history. got something wrong? yell at me.*
1028
-
1029
- Credit goes to Dragonoid (theory), CompactAI (proof) & the CompactAI crew
1030
- </script>
1031
- <script type="text/markdown" id="paper-apollonian_gasket-md"># Token Embeddings Inside an Integer Apollonian Gasket
1032
-
1033
- OK so Mage keeps bringing this up in #general and honestly it's the kind of thing that sounds like math fanfiction until you sit there for twenty minutes and then you're like... wait. Maybe not completely insane.
1034
-
1035
- The pitch: instead of learning token embeddings as giant float matrices through SGD, put every token as an address inside an Apollonian gasket, you know, that fractal you get when you recursively pack circles into the gaps between other circles forever, and key each address to a pair of twin primes.
1036
-
1037
- I know. Stick with me.
1038
-
1039
- ## the geometry, roughly
1040
-
1041
- Apollonian gasket comes out of Descartes' circle theorem. Four mutually tangent circles, their curvatures (1/radius) satisfy a quadratic relation. Start with three tangent circles, compute the two circles tangent to all three, pick one, recurse. You get this infinitely detailed fractal where every circle has an integer curvature. Provided you start with the right initial curvatures anyway.
1042
-
1043
- Circles in an integer gasket form a hierarchy. Big circles = small curvatures. Deeper = bigger curvatures. Circles tangent to each other are neighbors. And a circle's curvature encodes something about where it sits in the hierarchy, its position relative to everything else. That's the part that matters.
1044
-
1045
- ## the twin prime thing (this is where it gets weird)
1046
-
1047
- Mage's actual suggestion: map each token to a circle via f: token → (p₁, p₂) where p₁ and p₂ are twin primes. Primes differing by exactly 2, like 17 and 19. The +2 gap between twin primes maps naturally onto the local step structure of the gasket. "Semantic neighbors" come for free from number theory instead of co-occurrence stats.
1048
-
1049
- So the weight matrix, the thing that normally stores all the relationships between tokens as learned floats, becomes the curvature graph. Instead of "the embedding for cat is related to the embedding for dog by some learned vector" you get "the curvature of cat's circle has a specific Descartes relation to the curvature of dog's circle."
1050
-
1051
- Inference becomes bounded curvature recall: search circles with curvature ≤ K, filter by primality (make sure you're on valid addresses), verify Descartes-consistency (make sure geometric relations actually hold). It's deterministic. You're traversing a fixed structure, not predicting an embedding.
1052
-
1053
- ## wait, this might actually have something to it
1054
-
1055
- Few things from the back-and-forth in chat that make this better than your average 3am math thought:
1056
-
1057
- The structure is fixed. Normal embeddings are a black box, train em, they go somewhere, hope the geometry's nice. Gasket geometry is given. The question becomes whether it's useful, not whether you can learn a useful one. Different problem entirely.
1058
-
1059
- The twin prime mapping gives you a built-in closeness notion from number theory. Twin primes are conjectured infinite (unproven, sure, but more than enough for any practical vocab). And since they're spaced by exactly 2 you get a natural adjacency. Map semantically similar tokens to nearby primes and the geometry handles the rest.
1060
-
1061
- And it's absurdly compressible. You don't store a giant embedding matrix. You store the gasket generation algorithm and the vocab-to-prime-pairs mapping. 50k vocabulary? 50k integer pairs instead of 50k × 768 floats. Hundreds of megabytes down to kilobytes. Maybe tens of kilobytes. That's wild.
1062
-
1063
- ## the problems that nobody's solved
1064
-
1065
- Plenty. The chat wasn't pretending otherwise.
1066
-
1067
- Biggest one: how do you assign tokens to primes? Need a mapping from tokens to (p₁, p₂) pairs where semantically similar tokens end up near each other in the gasket. Random assignment = geometry is meaningless noise. But if you have to learn the assignment... you just moved the learning problem somewhere else. Nothing's free.
1068
-
1069
- Also the gasket is 2D. Token embeddings are usually 768D or higher. You're cramming high-dimensional semantics into a flat fractal. There are ways to extend Descartes to higher dimensions (Soddy's theorem generalizes), but the nice integer properties of the Apollonian gasket are a 2D thing specifically.
1070
-
1071
- "Bounded curvature recall" sounds neat, what's it actually mean for language modeling though? You're doing geometric lookup. How does attention even work here? Does attention make sense when "embeddings" are fixed positions?
1072
-
1073
- And twin prime conjecture is unproven. If twin primes are somehow finite (almost certainly not but we can't prove it) you'd run out of addresses. Even with infinite twin primes, the density thins, mapping a million tokens might force you into enormous primes and correspondingly enormous curvatures.
1074
-
1075
- ## building it (nobody has yet)
1076
-
1077
- Experiment would look like:
1078
-
1079
- Pick a small vocab, maybe 1000 tokens. Manually assign em to twin prime pairs, doesn't have to be perfect, just needs semantically related ones geometrically close. Build a tiny transformer where embedding lookup is replaced by gasket traversal. Model doesn't learn embeddings, it learns to navigate the structure. Train on something simple like next token prediction. See if it converges at all.
1080
-
1081
- Null hypothesis: it learns nothing useful cause the geometric prior is wrong. If it does learn? Interesting.
1082
-
1083
- Compare to identical model with learned embeddings. If the gasket version is even in the same ballpark, that's a big deal given the compression advantage.
1084
-
1085
- Mage suggested combining this with STM from the other paper, since you'd want to be picky about training examples when your embedding scheme is this constrained. But honestly combining two untested ideas sounds like a great way to not know which one's failing.
1086
-
1087
- ## anyone done this before?
1088
-
1089
- I looked. Nope. No literature on Apollonian gaskets for token embeddings.
1090
-
1091
- Nearest neighbors: hyperbolic embeddings (Poincaré ball) for hierarchies, but those are continuous, learned, no integer or prime structure. Some niche fractal initialization papers. Some knowledge graph stuff in hyperbolic/spherical geometries. Nothing using gaskets, twin primes, or curvature graphs as the embedding mechanism. Genuinely new ground. For better or worse.
1092
-
1093
- ## tldr
1094
-
1095
- - Tokens as circles in an integer Apollonian gasket, addressed by twin prime pairs
1096
- - Semantic neighbors geometrically close cause of Descartes curvature relations
1097
- - Weight matrix = curvature graph. Inference = curvature recall + primality filter + Descartes check
1098
- - Kilobytes instead of hundreds of megabytes for the embedding table
1099
- - Completely untested, might be mathematically impossible for high-dim semantics
1100
- - If it worked even a little... worth writing home about
1101
-
1102
- ---
1103
-
1104
- Credit goes to Mage & CompactAI
1105
- </script>
1106
- <script type="text/markdown" id="paper-overta_hypothesis-md"># The Overta Hypothesis: Knowledge-Free Foundation Models
1107
-
1108
- Amy's been working on something that sounds backwards: train a language model from scratch that knows nothing about the world. Not "knows less." Nothing. Model wouldn't know what a human is, wouldn't know Earth exists, wouldn't know what "Paris" or "coffee" or "gravity" means.
1109
-
1110
- What it would know: how to reason. How to hold a conversation. How to use tools to look stuff up. How to do in-context learning from whatever you feed it at inference time.
1111
-
1112
- OFM, Overta Foundation Model. She owns overta.org. Nothing on it yet, but the repo exists.
1113
-
1114
- The pitch is basically: cramming world knowledge into weights, which every LLM since GPT-2 does, wastes parameters. Instead, let the model spend its entire budget on reasoning. Facts live outside, in retrievable documents. The model's just the engine.
1115
-
1116
- ## what does "no world knowledge" actually look like
1117
-
1118
- Weirder than you'd think. When Amy says the model wouldn't know what a human is, she's literal. Here's the kind of definition she'd provide externally at inference time, via search tool or context window:
1119
-
1120
- > "We are entities interacting with the physical world and able to do precise manipulation and also self-locomotion, through deforming and displacing our body."
1121
-
1122
- Model's never seen this before. Doesn't come pre-loaded. But it knows how to use a definition once provided. Knows how to reason from premises. If X is an entity that can manipulate objects and you ask about X's capabilities, it references the definition. That's the whole thing.
1123
-
1124
- Training data would be purely synthetic conversations. Characters have defined properties stated explicitly in context. Reasoning chains spelled out step by step. Facts always grounded in explicitly provided info. Model never falls back on "common sense", there isn't any.
1125
-
1126
- Amy wrote seed examples by hand. The flavor:
1127
-
1128
- ```
1129
- <message from="other">
1130
- describe whats happening now
1131
- </message>
1132
- <message from="self">
1133
- <think>
1134
- They're asking me to describe "whats happening now". Right now I'm talking
1135
- to them and outputting text. I don't know of anything else happening now.
1136
- So I'll describe that to them.
1137
- </think>
1138
- I (some entity which processes text and outputs text) am conversing with
1139
- you, what I assume to be an entity which also can process text and output
1140
- text of your own. I'm outputting text to respond to your request.
1141
- </message>
1142
- ```
1143
-
1144
- Notice it doesn't say "I am an AI assistant." Says "I (some entity which processes text and outputs text)." Describes itself from first principles using only what's observable. The whole philosophy is in that one response.
1145
-
1146
- ## the arguments for it
1147
-
1148
- This crystallized across a bunch of conversations.
1149
-
1150
- Hallucination isn't a bug, it's the design. LLMs hallucinate because they're trained to memorize facts and spit em back probabilistically. Don't train em to memorize facts, they can't hallucinate facts. They can still fail to reason correctly, different failure mode entirely.
1151
-
1152
- Parameter efficiency. 350M model spending zero params on knowing the capital of France or the plot of Hamlet can spend all 350M on reasoning. Amy's guess: more intelligence per parameter than any model that mixes knowledge and reasoning.
1153
-
1154
- Grounding is explicit. When the model uses a fact you know exactly where it came from, context window, search tool, user provided it. No mystery about whether the model's "remembering" or "making it up."
1155
-
1156
- Also updatability. World knowledge changes, models don't. Model with no world knowledge has nothing to go stale. Just update the retrieval database. And alignment: model with no priors about true/false, good/bad, normal/weird only knows what you tell it in the moment. The user defines the ethical frame and factual premises, not the training data. Which obviously cuts both ways, Amy's aware.
1157
-
1158
- ## and the problems
1159
-
1160
- Nobody's pulled it off yet. Amy's early experiments have been rough.
1161
-
1162
- Language itself encodes knowledge, probably the biggest problem. Can't learn English grammar without incidentally learning that doctors treat patients, fire is hot, people have names. The boundary between "reasoning" and "knowing" is way blurrier than the hypothesis assumes. Costikoooo flagged this in chat: model might pick up unwanted world knowledge just from how conversations are structured.
1163
-
1164
- Cold start is brutal. Amy's pipeline: manually write ~200 seed examples → finetune Qwen3 4B to generate more → use that for the full training dataset. Seed examples have to be near-perfect, everything cascades from em. Claude Opus "doesn't get it even close first try and needs a lot of iterating." And the AI models she's using to generate training data were themselves trained on world knowledge, so they sneak it in. Recursive contamination basically.
1165
-
1166
- Her earlier procedural generators, pure code, no LLMs, produced a model that could tool-call but was "the most brittle thing imaginable." Only worked with names in its predefined list. Generalization terrible.
1167
-
1168
- Then there's in-context bandwidth: if every fact has to live in the context window you need a killer retrieval system and model becomes only as good as its RAG. Dragonoid also asked about ethics, what even counts as knowledge? Dragonoid asked about ethics. Amy said ethics would be taught as abstract values. But are values knowledge? Where's the line? Gets tangled fast.
1169
-
1170
- ## the procedural generation thing
1171
-
1172
- Amy's earlier approach, and the more interesting one honestly, ditched LLMs entirely. She built a system of TypeScript generators. Each function handles one aspect of conversation generation. One generator adds a user message like "My name is Joe," mutates conversation state so Joe's stored. Later generators reference that state. The system randomly chains generators together. All procedures, guaranteed consistent cause the state machine enforces it.
1173
-
1174
- Trained a 350M model from scratch on this procedural data. Qwen3 architecture, custom tokenizer, about an hour per training run on a 16GB GPU. Model learned to remember user names (generator state tracked em), search for info it didn't have (generators included search calls), stay in character as "an entity that processes text."
1175
-
1176
- But brittle. Only generalized to names in the generator's list. Math broken. Longer training mighta helped, only about an hour per run.
1177
-
1178
- Neat insight though: with this approach you add a new capability by writing a new generator and retraining. Timer? Timer generator. Spatial reasoning? Spatial generator. Capabilities are modular because the training data is modular.
1179
-
1180
- And it's philosophically cleaner than LLM-distillation. No world knowledge leaks in. But way more labor, you're writing a program that writes programs that simulate conversations, and you gotta anticipate every capability.
1181
-
1182
- ## where this needs to go
1183
-
1184
- Viable experiment:
1185
-
1186
- 1. Procedural generator covering ~20 distinct capabilities (name memory, search, clarification, multi-turn reasoning, simple math from provided formulas, etc.)
1187
- 2. Train small model (~100M) from scratch only on this data
1188
- 3. Test novel names, novel facts in context, novel combos of capabilities
1189
- 4. Compare to identical model on standard web text, does Overta model hallucinate less? Reason worse? Something in between?
1190
-
1191
- Amy's paused this to work on other stuff but the repo and approach are documented. Someone could pick it up.
1192
-
1193
- ## tldr
1194
-
1195
- - Train a model that knows zero facts, only reasoning and conversation
1196
- - All knowledge from context window or retrieval at inference time
1197
- - Training data procedurally generated, not scraped
1198
- - Claims: no hallucination (can't invent facts you never learned), better param efficiency, explicit grounding
1199
- - Problems: language encodes knowledge, procedural generation is labor-intensive, model brittle so far
1200
- - Amy poked at this with 350M models, promising, not there yet
1201
-
1202
- ---
1203
-
1204
- Credit goes to Amy & the CompactAI server
1205
- </script>
1206
- <script type="text/markdown" id="paper-attention_experiment-md"># An Experiment With Attention
1207
-
1208
- wop posted this on HuggingFace. Started simple: can you swap full attention for something cheaper and still keep enough context to nail the next token? Answer turned out to be "nope, not yet", but how it got there is more interesting than the headline.
1209
-
1210
- The setup is clean. Reproducible. Refreshing, no massive training runs, no "promising directions" handwaving. Just a concrete benchmark, two architectures, numbers.
1211
-
1212
- ## the actual question
1213
-
1214
- Context window isn't a flat sequence of tokens. It's usually: task instructions, style hints, formatting rules, actual content. These don't all matter at every token. Some rules are globally relevant but locally weak, the emoji rule in a system prompt, a formatting constraint. Model needs to carry them the whole way even when they don't matter at each individual prediction.
1215
-
1216
- wop's framing: can a compressed context state preserve those weak early rules as the sequence gets long? And how does that stack up against ordinary attention?
1217
-
1218
- ## two models, head to head
1219
-
1220
- Attention: standard causal transformer attention. The baseline.
1221
-
1222
- Compressed: replaces token-to-token attention with a learned compressed memory state, a few implicit slots.
1223
-
1224
- Important: the compressed model doesn't classify tokens into categories. It reads tokens, updates a compact state, predicts from that state. Structure stays implicit. No hand-crafted "this is a rule, this is content" partitioning.
1225
-
1226
- Dataset is synthetic and hardcoded (keeps it clean). Each example has two early rules, one item, a long distractor-filled prefix, and a target that requires recovering the early rules. The benchmark specifically stresses rule retention over distance, not general prediction.
1227
-
1228
- Context lengths: 64, 256, 1028.
1229
-
1230
- ## what happened
1231
-
1232
- Attention won. On quality. And on speed. Didn't expect the speed part.
1233
-
1234
- At ctx64: attention val_acc 0.938, rule_acc 0.906. Compressed: 0.699 and 0.492.
1235
-
1236
- At ctx256: attention 0.757 val_acc, 0.581 rule_acc. Compressed: 0.633 and 0.358.
1237
-
1238
- At ctx1028: attention 0.701 val_acc, 0.492 rule_acc. Compressed: 0.577 and 0.263.
1239
-
1240
- Speed was brutal. ctx1028: attention finished in about 10 seconds. Compressed took about 230. So it was less accurate AND 23x slower. Oof.
1241
-
1242
- ## the lesson (not "compression bad")
1243
-
1244
- People might see those numbers and go "welp attention wins, pack it up." That'd miss the point.
1245
-
1246
- Naive compressed recurrent context doesn't automatically beat attention. Obvious now. Wasn't obvious going in, plenty of people assumed compressing context would help with long-range stuff because you're forcing a summary. Numbers say nope. Not unless you're real careful about how you compress.
1247
-
1248
- Preserving weak parallel instructions is harder than keeping a rolling summary. The compressed model didn't just lose accuracy, it specifically tanked rule_acc. That's the game. Can you keep early constraints alive? Answer: not with a dumb bottleneck.
1249
-
1250
- Full attention is still stupidly strong, even on a benchmark literally designed to break it. That's kind of wild. Task was built to punish attention and it still held up.
1251
-
1252
- Also worth noting: the compressed model updates memory step-by-step in sequence order, tons of serial work. Attention gets all those optimized parallel kernels. Some of the speed gap is architecture, some is just the real world having better kernels for one approach.
1253
-
1254
- ## what this means
1255
-
1256
- wop doesn't over-claim. The motivating intuition, context isn't flat, some instructions matter globally but weakly, a good alternative to attention needs to preserve those signals, that's still solid. What broke is that the first compressed block was too simple. Formed a bottleneck. Just not a smart enough one.
1257
-
1258
- If you wanna replace or relax attention, the replacement probably needs: a smarter way to preserve weak long-range constraints (rule_acc tells you directly if you're failing), a more parallel implementation (230 seconds is useless), a more selective memory update (not every token matters for those early constraints), and a benchmark that measures rule retention directly, not hidden inside average loss.
1259
-
1260
- Next step: compress smarter, not harder.
1261
-
1262
- ## bottom line
1263
-
1264
- The experiment made the question concrete. No more abstract talk about "efficient context." There's a clear picture now. Attention expensive but extremely effective. Compressed context alone isn't enough. Weak parallel instructions are a real stress test.
1265
-
1266
- If cheaper context mechanisms are gonna work, they need to preserve global obligations without collapsing into a vague summary. Numbers are out there. Reproduce em or beat em.
1267
-
1268
- wop used Kaggle notebooks for GPU, Codex from OpenAI for assistance, HuggingFace ZeroGPU for the thumbnail. Repo at github.com/koo1140/attention-experiment.
1269
-
1270
- ---
1271
-
1272
- Credit goes to wop (poe) & CompactAI
1273
- </script>
1274
- <script type="text/markdown" id="paper-sparrow_fant-md"># Sparrow, FANT, and the Weird Stuff That Works
1275
-
1276
- Shane (Crownelius) posted this on HuggingFace after sitting on the story. It's part technical writeup, part personal history, part challenge. Here's a bunch of half-built things, some of them work way better than they should, come help figure out why.
1277
-
1278
- The headline: Sparrow, a 1M-parameter model, scores 95.6% on a 1,900-question math eval where Owl Alpha scores 61.4%. One million parameters versus a 70B-class model. Not a typo.
1279
-
1280
- ## how Shane got here
1281
-
1282
- Unusual route into model building. Dropped a finetune that scored weirdly high on EQ, the empathy benchmark nobody goes after. Publishing outfit reached out, wanted full books generated through Claude, architected prompt-by-prompt. Gig ran over $25k in API credits. Shane designed every prompt. About 60% of that publisher's pipeline still uses his curation.
1283
-
1284
- That flipped him from using models to building em. Tiny ones specifically, small enough for a 12GB card, small enough that every architectural choice is exposed and wrong decisions are embarrassing.
1285
-
1286
- ## FANT and stuff that shouldn't work
1287
-
1288
- FANT (github.com/Crownelius/fant3) is the experimentation framework. Three iterations, each a full rewrite, the kind you do when you care about findings, not code. Philosophy: at small scale you can try genuinely dumb ideas and actually see what they do. No hiding behind scale.
1289
-
1290
- The standout: SleepGate. A memory consolidation routine that fires every 100 training steps. Like half a screen of code, mostly comments. On FANT 2 at 5M parameters, 1,000-problem procedural math eval: +5.3 points. From one architectural decision. Same optimizer, same data, same schedule. Just a tiny consolidation pass wedged in.
1291
-
1292
- Why does that move the needle that much? Nobody's fully sure. But it does. That's the point of the framework, surface weird stuff so people can dig in.
1293
-
1294
- ## SpinorApollonian Memory (this is the newest weird thing)
1295
-
1296
- This one needs setup. Shane found a paper by Jerzy Kocik on tangency spinors, classifying Apollonian disk packings using 2D Minkowski spinors. Descartes' circle theorem turns out to be the Minkowski quadratic form in signature (1,3). Actual math, not metaphor.
1297
-
1298
- Application: memory writes get split by chirality. Left-spinning packs go to one bucket, right-spinning packs to another. Geometric routing instead of threshold routing.
1299
-
1300
- The failure mode that'd been a problem for two months, packs starving each other into uselessness, just vanished. Same pattern at every scale tested, 5M through 742M. Hard to believe. But the ablation table doesn't lie.
1301
-
1302
- "Sounds like peanut butter on a hamburger, but the ablation table says it works.", Shane
1303
-
1304
- ## Sparrow vs Owl Alpha
1305
-
1306
- Sparrow is separate from FANT. Different skeleton, different router, different everything. Small and surgical, built for math. Not general-purpose, not trying to be.
1307
-
1308
- Across 38 head-to-head evals (n=50 each, numeric scoring), Sparrow ties or beats Owl Alpha on 33 of 38. 87%.
1309
-
1310
- Five losses are on simple multiplication and division at digit counts where Owl's training data is dense. Fair wins, not the interesting ones.
1311
-
1312
- The interesting ones: Goldbach, Collatz, Fermat-little, complex modulus, dot products, distance, determinants. +100 percentage points in some cases. +98pp. +88pp.
1313
-
1314
- A 1M-parameter byte-level model beating a 70B-class frontier model by margins you'd normally assume are bugs. Shane checked twice, bothered three friends, re-ran at three temperatures. Same numbers. Makes you question how much of big-model performance is just brute force.
1315
-
1316
- Trick: Sparrow uses a calc-tag wrapper for arithmetic. It learns to call it correctly. 5-digit multiplication: Owl Alpha 12%, Gemma 3 27B 0%, Sparrow 100%. Model doesn't do math, learns to use the tool. That's the whole thing.
1317
-
1318
- ## unsolved: FANT + Sparrow fusion
1319
-
1320
- Shane can't get Sparrow's approach to work with FANT's architecture. Something about how Sparrow handles symbolic state should connect to FANT's recursion stack, but the fusion's been elusive for weeks. Breadcrumbs are public, repo's open, issues are open, the challenge is sitting there.
1321
-
1322
- "Half-built spaceships are best shared."
1323
-
1324
- ## tldr
1325
-
1326
- - FANT: experimentation framework for tiny models (5M–742M)
1327
- - SleepGate: 100-step consolidation pass, +5.3 points. Nobody knows exactly why
1328
- - SpinorApollonian Memory: geometric routing by chirality using Minkowski spinors, killed a starvation bug
1329
- - Sparrow: 1M-param math model beats Owl Alpha (70B-class) on 87% of evals. Not a typo
1330
- - Trick is tool use (calc-tag), not raw compute, Sparrow calls for help
1331
- - FANT + Sparrow fusion unsolved, open challenge
1332
-
1333
- ---
1334
-
1335
- Credit goes to Crownelius (Shane) & CompactAI
1336
- </script>
1337
-
1338
  <script>
1339
  var PAPERS = [
1340
  {
@@ -1515,13 +220,9 @@ Credit goes to Crownelius (Shane) & CompactAI
1515
  var view = document.createElement('div');
1516
  view.className = 'paper-view';
1517
  view.setAttribute('role', 'document');
1518
- view.setAttribute('aria-busy', 'true');
1519
  view.innerHTML =
1520
  '<button class="paper-view-close" aria-label="Close paper viewer">&times;</button>' +
1521
- '<div class="paper-view-loading" role="status">' +
1522
- '<div class="loading-spinner" aria-hidden="true"></div>' +
1523
- '<span style="color:var(--text-dim);font-family:Geist Mono,monospace;font-size:13px">Loading paper...</span>' +
1524
- '</div>';
1525
 
1526
  overlay.appendChild(view);
1527
  document.body.appendChild(overlay);
@@ -1529,16 +230,8 @@ Credit goes to Crownelius (Shane) & CompactAI
1529
 
1530
  var closeBtn = view.querySelector('.paper-view-close');
1531
 
1532
- // Focus the close button
1533
  closeBtn.focus();
1534
 
1535
- // Focus trap: find all focusable elements in the overlay
1536
- function getFocusableEls() {
1537
- return overlay.querySelectorAll(
1538
- 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
1539
- );
1540
- }
1541
-
1542
  var close = function() {
1543
  overlay.style.opacity = '0';
1544
  overlay.style.transition = 'opacity 0.2s ease';
@@ -1557,109 +250,12 @@ Credit goes to Crownelius (Shane) & CompactAI
1557
  overlay.addEventListener('click', function(e) {
1558
  if (e.target === overlay) close();
1559
  });
1560
-
1561
- // Escape key handler
1562
  document.addEventListener('keydown', function handler(e) {
1563
  if (e.key === 'Escape') {
1564
  close();
1565
  document.removeEventListener('keydown', handler);
1566
  }
1567
  });
1568
-
1569
- // Focus trap: keep Tab within the overlay
1570
- overlay.addEventListener('keydown', function(e) {
1571
- if (e.key !== 'Tab') return;
1572
- var focusable = getFocusableEls();
1573
- if (focusable.length === 0) return;
1574
- var first = focusable[0];
1575
- var last = focusable[focusable.length - 1];
1576
-
1577
- if (e.shiftKey) {
1578
- if (document.activeElement === first) {
1579
- e.preventDefault();
1580
- last.focus();
1581
- }
1582
- } else {
1583
- if (document.activeElement === last) {
1584
- e.preventDefault();
1585
- first.focus();
1586
- }
1587
- }
1588
- });
1589
-
1590
- // Load from embedded markdown
1591
- var mdEl = document.getElementById('paper-' + paper.id);
1592
- if (mdEl && mdEl.textContent) {
1593
- var parsed = parsePaper(mdEl.textContent.trim());
1594
- renderView(view, parsed, previousFocus, close, paper);
1595
- } else {
1596
- view.querySelector('.paper-view-loading').innerHTML =
1597
- '<p role="alert" style="color:var(--text-dim);font-family:Geist Mono,monospace;font-size:13px">Paper content not found.</p>';
1598
- view.removeAttribute('aria-busy');
1599
- }
1600
- }
1601
-
1602
- function parsePaper(md) {
1603
- var lines = md.split('\n');
1604
- var creditLine = '';
1605
- var contentLines = [];
1606
- var foundCredit = false;
1607
-
1608
- for (var i = lines.length - 1; i >= 0; i--) {
1609
- var trimmed = lines[i].trim();
1610
- if (!foundCredit && trimmed.toLowerCase().indexOf('credit goes to') === 0) {
1611
- creditLine = trimmed;
1612
- foundCredit = true;
1613
- } else {
1614
- contentLines.unshift(lines[i]);
1615
- }
1616
- }
1617
-
1618
- var contentMd = contentLines.join('\n').trim();
1619
- var html = marked.parse(contentMd);
1620
-
1621
- return { html: html, credit: creditLine };
1622
- }
1623
-
1624
- function renderView(view, parsed, previousFocus, closeFn, paper) {
1625
- var creditHtml = '';
1626
- if (parsed.credit) {
1627
- var creditText = parsed.credit;
1628
- var labelEnd = creditText.indexOf(':');
1629
- var labelPart = creditText.substring(0, labelEnd + 1);
1630
- var namesPart = creditText.substring(labelEnd + 1).trim();
1631
- creditHtml =
1632
- '<footer class="paper-credit" role="contentinfo">' +
1633
- '<span class="credit-label">' + escapeHtml(labelPart) + '</span> ' +
1634
- '<span class="credit-names">' + escapeHtml(namesPart) + '</span>' +
1635
- '</footer>';
1636
- }
1637
-
1638
- var proofHtml = '';
1639
- if (paper && paper.proof_script_content) {
1640
- proofHtml =
1641
- '<section class="proof-section" aria-label="Proof script">' +
1642
- '<div class="proof-label">&#x2713; Replication Script</div>' +
1643
- '<pre class="proof-script"><code>' + escapeHtml(paper.proof_script_content) + '</code></pre>' +
1644
- '</section>';
1645
- }
1646
-
1647
- view.innerHTML =
1648
- '<button class="paper-view-close" aria-label="Close paper viewer">&times;</button>' +
1649
- '<article class="paper-body" role="article" aria-label="Paper content">' + parsed.html + '</article>' +
1650
- proofHtml +
1651
- creditHtml;
1652
-
1653
- view.removeAttribute('aria-busy');
1654
-
1655
- // Re-bind close button using the shared close function
1656
- var closeBtn = view.querySelector('.paper-view-close');
1657
- closeBtn.addEventListener('click', closeFn);
1658
-
1659
- // Refocus close button so focus trap works after re-render
1660
- closeBtn.focus();
1661
-
1662
- announce('Paper loaded.');
1663
  }
1664
 
1665
  function escapeHtml(str) {
 
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
  <link href="https://fonts.googleapis.com/css2?family=Geist:wght@300..700&family=Geist+Mono:wght@400;500&display=swap" rel="stylesheet">
11
 
12
+ <link rel="stylesheet" href="everywhere.css">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  </head>
14
  <body>
15
 
 
40
  </div>
41
  </footer>
42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  <script>
44
  var PAPERS = [
45
  {
 
220
  var view = document.createElement('div');
221
  view.className = 'paper-view';
222
  view.setAttribute('role', 'document');
 
223
  view.innerHTML =
224
  '<button class="paper-view-close" aria-label="Close paper viewer">&times;</button>' +
225
+ '<iframe class="paper-view-frame" title="' + escapeHtml(paper.title) + '" src="Papers/' + paper.id + '.html"></iframe>';
 
 
 
226
 
227
  overlay.appendChild(view);
228
  document.body.appendChild(overlay);
 
230
 
231
  var closeBtn = view.querySelector('.paper-view-close');
232
 
 
233
  closeBtn.focus();
234
 
 
 
 
 
 
 
 
235
  var close = function() {
236
  overlay.style.opacity = '0';
237
  overlay.style.transition = 'opacity 0.2s ease';
 
250
  overlay.addEventListener('click', function(e) {
251
  if (e.target === overlay) close();
252
  });
 
 
253
  document.addEventListener('keydown', function handler(e) {
254
  if (e.key === 'Escape') {
255
  close();
256
  document.removeEventListener('keydown', handler);
257
  }
258
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  }
260
 
261
  function escapeHtml(str) {