<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Tools | How's it work</title><link>https://hsiw.io/blog/en/tags/tools/</link><description>I'm interested in how things work.</description><generator>Hugo</generator><language>en</language><lastBuildDate>Fri, 13 Nov 2026 00:00:00 +0900</lastBuildDate><atom:link href="https://hsiw.io/blog/en/tags/tools/index.xml" rel="self" type="application/rss+xml"/><item><title>Reading Lean Side by Side: Introducing Taiyak</title><link>https://hsiw.io/blog/en/posts/taiyak/</link><pubDate>Fri, 13 Nov 2026 00:00:00 +0900</pubDate><guid>https://hsiw.io/blog/en/posts/taiyak/</guid><description>Taiyak is a browser tool that splits Lean 4 source into declarations and shows each one next to a translation into natural-language mathematics.</description><content:encoded><![CDATA[<h2 id="i-made-taiyak">I made Taiyak</h2>
<p>I made Taiyak, a browser tool that splits Lean 4 source into declarations and shows each one next to a translation into natural-language mathematics. The name comes from the Japanese <em>taiyaku</em> (対訳), a text printed side by side with its translation.</p>
<ul>
<li>Web version: <a href="https://taiyak.pages.dev/">taiyak.pages.dev</a></li>
<li>Source: <a href="https://github.com/gotoken/taiyak">gotoken/taiyak</a> (BSD-2-Clause)</li>
</ul>
<p>It opens a GitHub URL (private repositories too), a ZIP file or a folder. It only reads the source and never runs Lean, so you need no Lean installation. Opened without a URL, it shows a demo: a formalization I tried on CRuby.</p>

<figure class="shot">
  <a href="https://hsiw.io/blog/ja/posts/taiyak/taiyak-en.png" data-lightbox data-w="2560" data-h="1520"><picture>
    <source media="(max-width: 600px)" srcset="https://hsiw.io/blog/ja/posts/taiyak/taiyak-en-narrow_hu_b42a8be6852b630b.webp 600w, https://hsiw.io/blog/ja/posts/taiyak/taiyak-en-narrow_hu_67ea2f9c5082a203.webp 984w" sizes="100vw" width="600" height="309">
    <img src="https://hsiw.io/blog/ja/posts/taiyak/taiyak-en_hu_e9743f95cd688a2e.webp" srcset="https://hsiw.io/blog/ja/posts/taiyak/taiyak-en_hu_e9743f95cd688a2e.webp 760w, https://hsiw.io/blog/ja/posts/taiyak/taiyak-en_hu_7bbc3e4584713e37.webp 1520w" sizes="(max-width: 800px) 100vw, 760px" width="760" height="451" alt="The Taiyak screen with the demo Statements.lean open: Lean code on the left, the English translation on the right. Clicking ∀ in proposition P1 pops up an explanation of the universal quantifier." loading="lazy" decoding="async">
  </picture></a>
  <figcaption>Click ∀ to see what it means</figcaption>
</figure>
<h2 id="it-started-with-the-cpython-formalization">It started with the CPython formalization</h2>
<p>It started when I read &ldquo;<a href="https://broyojo.com/python-formalization/">Formalizing CPython</a>&rdquo; by David Andrews and Chao Zhang. Working mainly with Claude Opus 5.5, they copy the functions of CPython 3.15.2 into Lean and check each one in four steps:</p>
<ol>
<li>Copy: rewrite the C or Python source in Lean, keeping error messages and edge cases</li>
<li>Test: run the Lean copy against the real CPython on at least 50,000 generated inputs per function</li>
<li>Prove: state a property and have the machine check it; if it is false, keep the counterexample</li>
<li>Check: another agent, one that did not write the copy, asks whether a broken implementation could still pass the proof</li>
</ol>
<p>So far they have written 613,318 lines of Lean, and along the way 418 bug reports have been filed against Python.</p>
<p>It looked fascinating, so I tried to read it, but being new to Lean I found the theorems hard to take in one by one. Later I also started an experiment applying the same method to CRuby&rsquo;s <code>range.c</code> (<code>rb_range_component_beg_len</code>, which normalizes range arguments). Taiyak&rsquo;s demo is the Lean files from that experiment.</p>
<h2 id="why-not-read-it-as-a-parallel-text">Why not read it as a parallel text?</h2>
<p>Before learning Lean from scratch, perhaps I could read it if mathematical prose sat right next to it. It is the same idea as a bilingual reader for language learners.</p>
<p>Lean, I thought, suits this well. Put an ordinary program into prose and you get an explanation of what it does, worded differently by every writer. A Lean theorem is itself a proposition, and a definition is a mathematical object. <code>∀ x, P x</code> can only be translated as &ldquo;for every x, P x&rdquo;. Because the right translation is nearly fixed as mathematics, setting it against the Lean also makes mistranslations easy to spot.</p>
<p>As an example, here is the normalization of the start index in the demo&rsquo;s <code>Spec.lean</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lean" data-lang="lean"><span class="line"><span class="cl"><span class="kn">def</span><span class="w"> </span><span class="n">specBeg</span><span class="w"> </span><span class="o">(</span><span class="n">i</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">Input</span><span class="o">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">Int</span><span class="w"> </span><span class="o">:</span><span class="bp">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="k">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">:</span><span class="bp">=</span><span class="w"> </span><span class="n">i</span><span class="bp">.</span><span class="n">b</span><span class="bp">.</span><span class="n">getD</span><span class="w"> </span><span class="mi">0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="k">if</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="bp">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="k">then</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="bp">+</span><span class="w"> </span><span class="n">i</span><span class="bp">.</span><span class="n">n</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="n">b</span><span class="w">
</span></span></span></code></pre></div><p>Next to it, Taiyak shows the heading &ldquo;Definition: normalized start B&rdquo; and the following formula, where b₀ is the start (0 if it is nil). Formulas are rendered with KaTeX.</p>
<span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>B</mi><mo>=</mo><mrow><mo fence="true">{</mo><mtable rowspacing="0.36em" columnalign="left left" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><msub><mi>b</mi><mn>0</mn></msub><mo>+</mo><mi>n</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo stretchy="false">(</mo><msub><mi>b</mi><mn>0</mn></msub><mo>&lt;</mo><mn>0</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>b</mi><mn>0</mn></msub></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo stretchy="false">(</mo><msub><mi>b</mi><mn>0</mn></msub><mo>≥</mo><mn>0</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">
B = \begin{cases} b_0 + n &amp; (b_0 &lt; 0) \\ b_0 &amp; (b_0 \ge 0) \end{cases}
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="katex-base"><span class="katex-strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.0502em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="katex-base"><span class="katex-strut" style="height:3em;vertical-align:-1.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">{</span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.69em;"><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="katex-sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">n</span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="katex-sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.19em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:1em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.69em;"><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="katex-sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span><span class="mclose">)</span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="katex-sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.19em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span><p>The only other line is &ldquo;negative values count from the end&rdquo;. Set against the three lines of Lean, you can tell at once whether the translation is right.</p>
<h2 id="why-lean-proofs-are-trusted">Why Lean proofs are trusted</h2>
<p>Lean proofs are trusted because the part that checks them is small, and a different implementation can check them again.</p>
<ul>
<li>Propositions are types, and proofs are terms of those types. Whether a proof is correct comes down to a mechanical check that the term has the type.</li>
<li>Only a small kernel does the checking. Automation such as tactics merely builds proof terms, and the kernel checks the result again, so even a bug in a tactic cannot get a false theorem through (<a href="https://lean-lang.org/doc/reference/4.35.0-rc1/">Lean reference</a>).</li>
<li>The kernel can be re-checked by other implementations: the official lean4checker, <a href="https://arxiv.org/abs/2403.14064">Lean4Lean</a> written in Lean, Nanoda written in Rust and others. You do not have to trust the whole Lean implementation (<a href="https://lean-lang.org/faq">Lean FAQ</a>).</li>
<li>The axioms a proof relies on are recorded. If <code>#print axioms</code> shows only the standard <code>propext</code>, <code>Classical.choice</code> and <code>Quot.sound</code>, all is well. <code>sorry</code> shows up as <code>sorryAx</code>, and <code>native_decide</code> as <code>Lean.trustCompiler</code>, which trusts the whole compiler, so shortcuts cannot hide (<a href="https://lean-lang.org/doc/reference/4.29.0/ValidatingProofs/">Validating a Lean Proof</a>).</li>
</ul>
<p>What this guarantees, though, is only that the proof is correct. What a theorem statement means is a separate question, which I come back to below.</p>
<h2 id="why-lean-and-not-rocq-a-guess">Why Lean and not Rocq? (a guess)</h2>
<p>Most companies working on theorem proving with AI use Lean. OpenAI used Coq (now Rocq) for GamePad in 2018, then moved to Lean (<a href="https://arxiv.org/pdf/2605.27485">a summary of the history</a>), and its openai/math release in 2026 is formalized in Lean 4 and Mathlib (<a href="https://hyper.ai/en/datasets/openai-math">dataset description</a>). The reasons have not been stated, so what follows is my guess.</p>
<ul>
<li><strong>Mathlib exists.</strong> It is one huge mathematics library, useful both as training data and as the vocabulary for stating problems. The CSLib paper also says Mathlib played a large part in training AI for mathematical reasoning (<a href="https://arxiv.org/abs/2602.04846">CSLib</a>).</li>
<li><strong>Ordinary mathematics can be written as it is.</strong> Mathlib&rsquo;s culture uses the law of excluded middle and proof by contradiction freely. Paulson sees the Rocq community&rsquo;s insistence on constructive proof as having held back its use in mathematics, leaving that ground to Lean (<a href="https://lawrencecpaulson.github.io/2026/04/23/Why_not_Lean.html">Why not just use Lean?</a>).</li>
<li><strong>It is also a programming language.</strong> Lean definitions can be compiled and run. The &ldquo;Test&rdquo; step of the CPython formalization works by actually running the Lean copy and comparing it with CPython.</li>
<li><strong>It is easy to drive from an agent.</strong> elan and lake give a single toolchain, so setting up is not a puzzle.</li>
<li><strong>Pass or fail is clear-cut.</strong> Whether the kernel accepts a proof serves directly as the reward in reinforcement learning.</li>
</ul>
<p>Rocq has not stepped back, though. In October 2026 Anthropic and Theorem used Rocq to prove that 123 libraries do not crash, at the level of RISC-V machine code (<a href="https://letsdatascience.com/blog/claude-wrote-180-million-lines-of-proofs-only-on-risc-v">coverage</a>). Perhaps the split is Lean for mathematics and the meaning of languages, and Rocq for verification that builds on accumulated machine semantics.</p>
<h2 id="generated-lean-still-has-to-be-read-by-people">Generated Lean still has to be read by people</h2>
<p>The kernel guarantees only that &ldquo;this statement was shown by this proof&rdquo;, not that the statement says what you meant. The Lean reference too treats whether a proof is correct and what a theorem statement means as separate questions. It also counts unreviewed AI-generated proofs among those to be handled with the same caution as malicious ones (<a href="https://lean-lang.org/doc/reference/4.29.0/ValidatingProofs/">Validating a Lean Proof</a>).</p>
<p>Three pitfalls are common:</p>
<ul>
<li>The premises cannot be satisfied, so the theorem is vacuously true</li>
<li>A definition is mistranscribed: the proof is correct, but about a definition that differs from the implementation</li>
<li>The proposition proved is weaker than the property you wanted</li>
</ul>
<p>The &ldquo;Check&rdquo; step of Formalizing CPython is exactly the step that looks for these. In my CRuby experiment too, AI proposed the propositions and premises, and I confirmed them before moving on to the proofs. <code>NonVacuity.lean</code> holds concrete inputs that satisfy each theorem&rsquo;s premises, showing that none is vacuous.</p>
<p>In other words, what people need to read is not the proofs but the definitions and theorem statements. Proofs are the kernel&rsquo;s job; statements are ours. That is also why Taiyak folds long proofs from the start: I want the statements read first.</p>
<p>Taiyak&rsquo;s translations are LLM output too, so they can be wrong. That is why they sit next to the Lean, where they can be checked against it, instead of replacing it.</p>
<h2 id="how-to-use-it">How to use it</h2>
<ol>
<li>Open the <a href="https://taiyak.pages.dev/">web version</a>, enter a GitHub URL and press &ldquo;Open&rdquo;</li>
<li>In &ldquo;Settings&rdquo;, enter an API key from Anthropic, OpenAI, Google or OpenRouter. For a private repository, also enter a GitHub token: a link in Settings opens GitHub&rsquo;s token page with read-only access and a 30-day expiry already filled in</li>
<li>Press &ldquo;Translate this file&rdquo;, or &ldquo;Translate&rdquo; on a single block</li>
</ol>
<p>To help with reading:</p>
<ul>
<li><strong>Click Lean code for hints.</strong> For an identifier you get a summary of its definition and a jump to it; symbols such as <code>∀</code> and tactics such as <code>omega</code> and <code>rcases</code> get a short explanation</li>
<li>&ldquo;Ask Claude about this spot&rdquo; lets you ask a question with the declaration as context</li>
<li>When translating, Taiyak follows imports and sends the definitions the code refers to as context</li>
<li>Translations are kept in the browser. Export them as JSON and commit them to the repository&rsquo;s <code>.taiyak/</code>, and anyone can read the translations without an API key</li>
<li>The URL in the address bar is a share link, and pressing a declaration&rsquo;s line numbers copies a link to that declaration</li>
</ul>
<h2 id="design-decisions">Design decisions</h2>
<h3 id="limiting-where-data-can-go-with-headers">Limiting where data can go, with headers</h3>
<p>Taiyak handles API keys and sometimes private source code. Rather than explaining in code that it sends nothing anywhere else, I thought it would be easier to verify if the browser enforced it.</p>
<p>The web version returns a Content-Security-Policy from Cloudflare Pages&rsquo; <code>_headers</code>. Its <code>connect-src</code> lists only the GitHub API and four LLM APIs, so if the page tries to send anything anywhere else, the browser refuses.</p>
<pre tabindex="0"><code>connect-src https://api.github.com https://api.anthropic.com https://api.openai.com https://generativelanguage.googleapis.com https://openrouter.ai
</code></pre><p>The inline script is pinned by its sha256, with <code>default-src 'none'</code>, <code>form-action 'none'</code>, <code>frame-ancestors 'none'</code> and <code>Referrer-Policy: no-referrer</code> as well. The build output is committed to the repository and CI checks that it matches the source, so what is served can be read on GitHub as it is.</p>
<h3 id="masking-without-a-password-field">Masking without a password field</h3>
<p>If the API key field were <code>type=&quot;password&quot;</code>, the password managers in Chrome and Safari would react and offer to save it as this site&rsquo;s login password. An API key is not for logging in to this site, so that gets in the way.</p>
<p>So the field is an ordinary text input, masked with the CSS <code>-webkit-text-security: disc</code>, and an eye button toggles visibility. Only browsers without that CSS fall back to <code>type=&quot;password&quot;</code>. The field also carries attributes that tell 1Password, Bitwarden and the like to ignore it. Keys are used only inside the browser, and saved to localStorage only if you choose &ldquo;Remember in this browser&rdquo;.</p>
<p>Honestly, though, I am torn. API keys are exactly what I would like to keep in a password manager: not as a login password, but with the manager acting as a vault for tokens. If you know a good way to do that, please tell me.</p>
<h3 id="matching-the-interface-language-to-the-translation">Matching the interface language to the translation</h3>
<p>Translations in Korean with the interface in Japanese would look awkward. So there is a single language choice, and the translations, the interface, the glossary and Claude&rsquo;s explanations all follow it. Interface text is built in for ten languages (Japanese, English, Simplified and Traditional Chinese, Korean, French, German, Spanish, Portuguese and Russian); other languages get the English interface. A setting can also fix the interface language on its own.</p>
<p>Right-to-left languages such as Arabic and Hebrew are untested. Typing the language name should produce translations, but I cannot read them, so I cannot judge whether the display is right. Anyone willing to try is welcome.</p>
<h2 id="what-i-wish-were-different">What I wish were different</h2>
<p>Translating needs an LLM API key. Taiyak cannot use the allowance of flat-rate plans such as Claude Pro or ChatGPT Plus today. Translating on the plan you already pay for would be the easiest, but that is not how it works.</p>
<p>There are a few workarounds:</p>
<ul>
<li>Publish <code>dist/claude-artifact.html</code> as a claude.ai artifact, and each viewer translates with their own Claude account, with no API key. Pages inside claude.ai cannot reach GitHub, though, so you download the repository as a ZIP and load that</li>
<li>OpenRouter&rsquo;s free models are available</li>
<li>Google&rsquo;s Gemini API has a free tier. It is crowded, though: a translation of a single block took about three minutes to arrive. Gemini 4 Argon is not available on the free tier</li>
<li>Commit the translations to <code>.taiyak/</code>, and readers need no key at all</li>
</ul>
<p>As for ChatGPT, Sign in with ChatGPT arrived in September, letting Plus and Pro allowances be brought into outside tools without an API key. It covers products of participating partners, 16 at launch (<a href="https://itbrief.com.au/story/openai-launches-chatgpt-sign-in-for-16-partner-tools">itbrief</a>). I found no form that a personal site can freely build in, so I am watching it as a future option.</p>
<p>I also tried supporting Gemini Nano, built into Chrome (the Prompt API). It needs no key and the code never leaves the device, which is appealing. But it is a small model, and translating Lean into mathematics seems too much for it: its translations fall short of the API models, and long declarations may not fit its input limit.</p>
<h2 id="closing">Closing</h2>
<p>Lean written by AI is going to grow fast. With the kernel checking the proofs, what is left for people is reading whether &ldquo;this statement is really the right one&rdquo;. I hope Taiyak becomes a way in for people new to Lean to join that work.</p>
<h3 id="references">References</h3>
<ul>
<li><a href="https://broyojo.com/python-formalization/">Formalizing CPython</a> (David Andrews, Chao Zhang)</li>
<li><a href="https://lean-lang.org/doc/reference/4.29.0/ValidatingProofs/">Validating a Lean Proof</a> (Lean Language Reference)</li>
<li><a href="https://lean-lang.org/faq">Lean FAQ</a></li>
<li><a href="https://arxiv.org/abs/2403.14064">Lean4Lean: Towards a formalized metatheory for the Lean theorem prover</a> (Mario Carneiro)</li>
<li><a href="https://lawrencecpaulson.github.io/2026/04/23/Why_not_Lean.html">Why not just use Lean?</a> (Lawrence C. Paulson)</li>
<li><a href="https://arxiv.org/abs/2602.04846">CSLib: The Lean Computer Science Library</a></li>
<li><a href="https://arxiv.org/pdf/2605.27485">Automating Formal Verification with Agent-Guided Tree Search</a></li>
<li><a href="https://hyper.ai/en/datasets/openai-math">openai-math dataset</a></li>
<li><a href="https://letsdatascience.com/blog/claude-wrote-180-million-lines-of-proofs-only-on-risc-v">Claude wrote 180 million lines of proofs</a></li>
</ul>
]]></content:encoded></item></channel></rss>