<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[AlanLan: Tech & AI]]></title><description><![CDATA[AI tools, quantitative trading, and software engineering — building things that work]]></description><link>https://whetan.substack.com/s/tech-and-ai</link><image><url>https://substackcdn.com/image/fetch/$s_!rHk-!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff672ae68-b2d7-4107-9d9a-38f277491169_736x736.png</url><title>AlanLan: Tech &amp; AI</title><link>https://whetan.substack.com/s/tech-and-ai</link></image><generator>Substack</generator><lastBuildDate>Wed, 24 Jun 2026 20:08:17 GMT</lastBuildDate><atom:link href="https://whetan.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Qylan]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[whetan@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[whetan@substack.com]]></itunes:email><itunes:name><![CDATA[Whet]]></itunes:name></itunes:owner><itunes:author><![CDATA[Whet]]></itunes:author><googleplay:owner><![CDATA[whetan@substack.com]]></googleplay:owner><googleplay:email><![CDATA[whetan@substack.com]]></googleplay:email><googleplay:author><![CDATA[Whet]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[The Hardest Part of Modern C++ Isn't the Language.]]></title><description><![CDATA[A pipe organ, a Swiss watch, and the tool that made C++23 playable again.]]></description><link>https://whetan.substack.com/p/the-hardest-part-of-modern-c-isnt</link><guid isPermaLink="false">https://whetan.substack.com/p/the-hardest-part-of-modern-c-isnt</guid><dc:creator><![CDATA[Whet]]></dc:creator><pubDate>Fri, 20 Mar 2026 06:36:12 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/d1a385e9-3a7d-4f71-b030-b66bdbd54b1f_1200x630.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I&#8217;ve been a C programmer for most of my career. The kind who can feel what the CPU is doing. Move a register here, touch a block of memory there, shave off a microsecond. When you think at that level for long enough, you start to resent anything that calls itself &#8220;modern.&#8221;</p><p>Not because you can&#8217;t learn it. Because it feels wrong. Too many layers between you and the metal.</p><h2>C with classes</h2><p>For years, my C++ was really just C with classes. I found out later that most people who put &#8220;C++ engineer&#8221; on their resume are doing exactly the same thing. That&#8217;s where you plateau, and it&#8217;s a comfortable plateau. You ship code. It works. Nobody complains.</p><p>And a lot of people never leave that plateau. I&#8217;m not talking about junior developers. I&#8217;m talking about engineers with decades of C experience who never made the jump. The mental model of C is: I own every byte, I control every allocation, I decide when memory lives and dies. Accepting that a destructor will clean up for you, that you should <em>stop</em> calling <code>delete</code>, that <code>std::unique_ptr</code> knows better than you do when to free memory&#8230; that goes against everything a C programmer was trained to believe. Plenty of good engineers looked at that and said no thanks.</p><p>I almost did too. But then <code>std::vector</code> clicked. Then RAII clicked. Then I ran into <code>compare_exchange_strong</code> and <code>compare_exchange_weak</code> and spent a full day understanding when to use which one. Then C++17 arrived with SFINAE and template metaprogramming.</p><p>I questioned my life choices.</p><h2>50,000 lines by hand</h2><p>But I kept going, because the payoff was real.</p><p>My first serious Modern C++ project was a bridge layer between a trading platform and a strategy execution service. About 50,000 lines, took six months to write by hand. I picked C++ for speed and RAII, and the results justified the pain: on Windows 10, the process started at 22MB of memory, dropped to 11MB after running for a week. On Windows 11, 36MB at start, 12MB after a week. It was pulling tick data for every instrument at full frequency, the entire time.</p><p>That was the stage where I could <em>use</em> Modern C++. Vectors, smart pointers, move semantics, atomics. I&#8217;d crossed the first two hurdles: from C to C-with-classes, and from C-with-classes to C++11/14. Both were hard. Both filtered out a lot of people.</p><p>But those were hurdles you could clear on your own. Give a determined programmer enough time, and RAII will click. Move semantics will click. Smart pointers will click.</p><p>The third hurdle is different.</p><h2>The pipe organ</h2><p>A pipe organ is the most complex instrument ever built. Thousands of pipes. Four or five keyboards stacked on top of each other, called manuals. A pedalboard at your feet for the bass lines. Dozens of stops that change the sound of every pipe. To play it, you need both hands working different keyboards, both feet on the pedals, and somehow you also need to pull stops in the middle of a piece.</p><p>That&#8217;s four hands&#8217; worth of work. You have two.</p><p>Modern C++ past C++17 is a pipe organ.</p><p>The vertical span alone is disorienting. At the bottom, you&#8217;re still dealing with cache lines, branch prediction, and what the CPU is actually doing with your <code>alignas(std::hardware_destructive_interference_size)</code>. At the top, you&#8217;re writing <code>concepts</code> and <code>consteval</code> functions that execute entirely during compilation. You need to hold both levels in your head at the same time, because a one-line change at the top can restructure what happens at the bottom.</p><p>Then there&#8217;s the depth. Every line of C++23 is a reverse derivation. <code>std::expected&lt;Value, Error&gt;</code> looks like one line. Behind it is a chain of compiler decisions about storage layout, copy elision, destructor sequencing, and exception-free error propagation that traces all the way back to what would have been fifty lines of C with manual error codes and goto cleanup blocks.</p><p>And the sheer width of the thing. Templates. Concepts. Coroutines. Ranges. Modules. PMR. SIMD intrinsics versus portable abstractions. <code>constexpr</code> versus <code>consteval</code> versus <code>constinit</code>. Even the experts specialize. A template metaprogramming wizard might not know the first thing about coroutine frame allocation. A SIMD specialist might never touch ranges.</p><h2>The Swiss watch inside</h2><p>Here&#8217;s the thing people miss when they complain about C++ being too complex: this isn&#8217;t a design failure. This is a price.</p><p>A mechanical watch movement has hundreds of components, machined to micron tolerances. It&#8217;s absurdly complex. But it&#8217;s complex because it chose to tell time without a battery, without a circuit board, without any external dependency. That constraint, total self-reliance with precision, is what forces the complexity. A quartz watch does the same job with a battery and a chip. Cheaper, more accurate, simpler. But the mechanical watch gives you something the quartz watch can&#8217;t: it runs on nothing but itself.</p><p>Modern C++ made the same bargain. Zero-cost abstractions. Full hardware control. Compile-time safety. No garbage collector, no runtime, no VM. The language chose to give you everything, from register-level performance to type-level metaprogramming, in one system. That commitment to not compromise on any axis is what makes it so powerful. And it&#8217;s exactly what makes it so hard to hold in one head.</p><p>The organ doesn&#8217;t have five keyboards because the builder was a sadist. It has five keyboards because the music demands that range.</p><h2>1,000 lines to 10</h2><p>You want to see what that bargain looks like in practice? Look at the FIX protocol engine space.</p><p><a href="https://github.com/quickfix/quickfix">QuickFIX</a> was the industry standard for years. It was written in C++98/03 style, and the engineers who built it were not amateurs. To get acceptable performance, they had to hand-craft everything. A custom object pool: about 1,000 lines of carefully debugged code. A lock-free queue for market data: another 500 lines. Manual cache-line alignment to prevent false sharing: 200 more lines. Months of debugging and tuning before any of it was production-ready.</p><p>In C++23, the same functionality looks like this:</p><pre><code><code>std::pmr::monotonic_buffer_resource pool_{64_MB};    // object pool
SPSCQueue&lt;T, 4096&gt; queue_;                           // lock-free queue
alignas(std::hardware_destructive_interference_size) // cache alignment
</code></code></pre><p>Three lines. Works correctly out of the box.</p><p>Or take tag lookup. In the QuickFIX era, you&#8217;d write a giant switch statement or build a <code>std::unordered_map</code> at startup. Fifty-plus cases, each a runtime branch, hundreds of lines:</p><pre><code><code>std::string get_tag_name(int tag) {
    switch (tag) {
        case 8:  return "BeginString";
        case 35: return "MsgType";
        case 49: return "SenderCompID";
        // ... 50+ more cases
    }
}
</code></code></pre><p>In C++23, you write a <code>consteval</code> function. The entire table gets computed during compilation. At runtime, looking up tag 35 is a single array index. No branches, no hash lookups:</p><pre><code><code>consteval auto create_tag_table() {
    std::array&lt;TagEntry, MAX_TAG&gt; table{};
    table[8]  = {TagInfo&lt;8&gt;::name, TagInfo&lt;8&gt;::is_header};
    table[35] = {TagInfo&lt;35&gt;::name, TagInfo&lt;35&gt;::is_header};
    // ...
    return table;
}
inline constexpr auto TAG_TABLE = create_tag_table();  // zero runtime cost
</code></code></pre><p>Or SFINAE versus concepts. Constraining a session handler type in the old way required 200 lines of <code>std::enable_if_t</code> nested inside template parameter lists, producing error messages that no human could read. In C++23:</p><pre><code><code>template &lt;typename T&gt;
concept SessionHandler = requires(T&amp; h, const ParsedMessage&amp; msg) {
    { h.on_app_message(msg) } noexcept;
    { h.on_send(std::declval&lt;std::span&lt;const char&gt;&gt;()) } noexcept -&gt; std::same_as&lt;bool&gt;;
    { h.on_state_change(SessionState{}, SessionState{}) } noexcept;
    { h.on_error(SessionError{}) } noexcept;
};
</code></code></pre><p>Twenty-five lines. Reads like documentation. And when something doesn&#8217;t satisfy the concept, the compiler says &#8220;T does not satisfy SessionHandler&#8221; instead of vomiting 500 lines of template substitution failure.</p><p>None of this means the QuickFIX engineers&#8217; work was wasted. The opposite. Their 1,000 lines of hand-crafted optimization became the blueprint for the next standard. <code>std::pmr</code> exists because people like them proved that custom allocators matter. Concepts exist because SFINAE was so painful that the committee had to find a better way. Every one-line C++23 idiom is standing on the shoulders of someone who wrote the 1,000-line version first.</p><p>But it also means that every line of C++23, that clean, compact, one-line call, is carrying the cognitive weight of those 1,000 lines inside it. The complexity didn&#8217;t disappear. It got absorbed into the language. And now you need to understand what&#8217;s happening beneath that one line, or you&#8217;ll misuse it in ways that compile fine and fail silently at scale.</p><p>C17 through C23 didn&#8217;t just raise the bar. They added three more keyboards to the organ. The instrument kept growing, and one person&#8217;s hands didn&#8217;t.</p><h2>The planet I couldn&#8217;t reach</h2><p>Here&#8217;s what that third hurdle looks like up close.</p><p>I have a set of compile-time sorting algorithms sitting in my code archive. QuickSort, MergeSort, HeapSort. All three run during compilation. Not at runtime. During compilation.</p><pre><code><code>template&lt;int... Vs&gt;
struct arr {};

using input = arr&lt;5, 3, 8, 1, 9&gt;;
using sorted = quicksort_t&lt;input&gt;;  // arr&lt;1, 3, 5, 8, 9&gt;
</code></code></pre><p>The input is a type. The output is a type. The sorting happens when the compiler processes your code, and at runtime the cost is zero.</p><p>To make this work, you need a full toolkit of compile-time operations: <code>filter</code>, <code>concat</code>, <code>take</code>, <code>drop</code>, <code>merge</code>, <code>prepend</code>, all implemented as template specializations. The QuickSort partitions around a pivot using template predicates. The MergeSort splits the type in half, sorts recursively, and merges with ordered comparison. Even the correctness checks are compile-time:</p><pre><code><code>static_assert(std::is_same_v&lt;quicksort_t&lt;arr&lt;5,4,3,2,1&gt;&gt;, arr&lt;1,2,3,4,5&gt;&gt;);
static_assert(is_sorted_v&lt;mergesort_t&lt;arr&lt;9,7,5,3,1,8,6,4,2,0&gt;&gt;&gt;);
</code></code></pre><p>If any of those fail, the code doesn&#8217;t compile. The tests run before the binary even exists.</p><p>I wrote these. It was not easy, not quick, and not something I could have figured out by reading cppreference for an afternoon. Template metaprogramming at this level is a different language wearing C++ syntax as a disguise. You&#8217;re not writing instructions for the CPU. You&#8217;re programming the compiler.</p><p>And this is one stop on the pipe organ. One. There&#8217;s <code>consteval</code>, concepts, ranges, coroutines, modules, and every three years the language adds another row of pipes.</p><h2>The registrant</h2><p>Here&#8217;s the thing about pipe organs: historically, the organist never played alone.</p><p>There was always a person next to them called the registrant. The registrant pulled stops, turned pages, managed the wind supply. Not because the organist was bad. Because the instrument required more hands than any human has.</p><p>Modern electronic organs solved part of this with combination actions: memory banks that store complete stop configurations. Instead of the registrant pulling twelve stops one by one between movements, the organist presses a single button and the entire registration changes instantly.</p><p>The registrant didn&#8217;t make the organ simpler. The organ is exactly as complex. But the registrant made it <em>playable</em>.</p><p>AI is the registrant for Modern C++. And when you give it the right instructions, it doesn&#8217;t just pull stops. It pulls the <em>right</em> stops.</p><p>When I started building <a href="https://github.com/SilverstreamsAI/NexusFix">NexusFix</a>, a high-performance FIX protocol engine in C++23, I didn&#8217;t just throw code at AI and hope for the best. I wrote a rulebook. Not vaguely. Specifically.</p><p>Mandatory patterns: C++23 standard compliance, zero-copy data flow with <code>std::span</code> and move semantics, compile-time optimization with <code>consteval</code> and <code>constexpr</code>, memory sovereignty through PMR pools and cache-line alignment, type safety with strong types and <code>[[nodiscard]]</code>, deterministic execution with <code>noexcept</code> and no exceptions on hot paths.</p><p>Prohibited patterns: no <code>new</code>/<code>delete</code> on hot paths, no <code>virtual</code> functions in performance-critical code, no <code>std::shared_ptr</code> on hot paths, no floating-point for prices, no dynamic memory allocation during message parsing.</p><p>Forty-five numbered techniques, each mapped to specific source files. A six-phase optimization roadmap with measurable success criteria: zero hot-path allocations, cache miss rates below 5%, branch miss rates below 1%. A benchmark framework specifying exactly how to measure, down to RDTSC timing with <code>lfence</code> barriers and cache-line contention tests.</p><p>When AI has this kind of context, it doesn&#8217;t guess about <code>std::expected</code> versus exceptions. The rulebook says no exceptions on hot paths, use <code>std::expected</code>, target deterministic control flow. The decision is already made. AI implements it correctly, in the specific codebase, following the established patterns.</p><p>The problem was never that AI couldn&#8217;t write good C++23. The problem was that without constraints, it had to guess at hundreds of decisions that each require deep domain knowledge. Give it the constraints, and it stops guessing.</p><p>Remember those QuickFIX-era 1,000-line object pools? My rulebook has one line about them: &#8220;Use <code>std::pmr::monotonic_buffer_resource</code> for hot path allocation.&#8221; AI reads that, implements the pool with pre-allocation and per-message reset, following the established memory patterns. Hot-path allocations dropped from 12 per message to zero. The 1,000 lines of knowledge that QuickFIX engineers accumulated over years is now compressed into one rule that AI can execute in an afternoon.</p><p>SIMD selection: I described the workload, AI prototyped implementations with raw intrinsics, Highway, and xsimd, all following the project&#8217;s zero-copy and cache-alignment rules. xsimd won. The delimiter scan went from ~150ns to under 12ns. Thirteen times faster.</p><p>Compile-time lookup tables: the rulebook includes <code>consteval</code> protocol hardening. AI generated tag lookup tables from the FIX specification, replacing those 300 runtime switch branches the old way required, with compile-time verification that every entry was correct. Improvement ranged from 55% to 97%.</p><p>Each of these was a stop on the organ. With proper instructions, AI pulled them correctly.</p><h2>What actually changed</h2><p>When C++ reached C++17 and kept going, the language outgrew what one person could handle. The organ got more keyboards, more stops, more pipes. The music it could produce was extraordinary. But the number of hands you&#8217;d need to play it kept growing.</p><p>AI is the tool that lets us take Modern C++ back.</p><p>Not by making it simpler. C23 is more complex than C17, which was more complex than C++11. More features, more interactions between features, more ways to get subtly wrong results that compile without complaint.</p><p>What collapsed is the time between knowing and doing. &#8220;I know <code>std::expected</code> exists&#8221; to &#8220;I have a benchmarked, integrated implementation&#8221; used to take days. Now it takes hours. &#8220;I&#8217;ve heard of PMR&#8221; to &#8220;my hot path has zero allocations&#8221; used to take a week. Now it takes a day. The gap between reading about a C23 feature and actually deploying it in production code has always been the widest in C. Years wide, sometimes. Careers wide.</p><p>AI didn&#8217;t close that gap. It made it crossable.</p><p>You still need to know what you&#8217;re doing. If I didn&#8217;t understand RAII, or what a cache line is, or why branch misprediction costs you 15 cycles, no amount of AI could help me write a meaningful rulebook. The organist still needs to know music. The registrant handles the logistics so the organist can focus on playing.</p><p>But here&#8217;s what I learned: the registrant needs a score to follow. When I gave AI vague instructions, I got vague C++. When I gave it forty-five specific techniques, mandatory patterns, prohibited patterns, measurable success criteria, and a benchmark framework, it gave me code I could review and ship. The precision of the output matched the precision of the input.</p><p>The organ is exactly as complex as it was before. The music demands it. But with a registrant who knows the score, one person can play it again.</p><p><a href="https://github.com/SilverstreamsAI/NexusFix">NexusFix</a> parses FIX execution reports in 246 nanoseconds. Three times faster than QuickFIX. The hot path does zero allocations. The SIMD pipeline processes delimiters at 13x scalar speed. I built it in C++23, using AI as a constant collaborator on every technical decision, constrained by a rulebook that left nothing to chance.</p><p>The hardest part of Modern C++ was never the language. It was doing it alone.</p><p>You don&#8217;t have to anymore.<br></p><p></p><div><hr></div><p><br><em>The author builds high-performance C++ trading systems at <a href="https://github.com/SilverstreamsAI">SilverstreamsAI</a>. <a href="https://github.com/SilverstreamsAI/NexusFix">NexusFix</a> is an open-source FIX protocol engine in C++23.</em></p><p><em>He also writes <a href="https://open.substack.com/pub/alanlan/p/the-ancient-mirror-of-immortality">The Ancient Mirror of Immortality</a>, a hard sci-fi serial where C++ concepts are the laws of physics.</em></p>]]></content:encoded></item><item><title><![CDATA[The Trident and The Green Ox]]></title><description><![CDATA[I&#8217;ve been writing code for a few decades now.]]></description><link>https://whetan.substack.com/p/the-trident-and-the-green-ox</link><guid isPermaLink="false">https://whetan.substack.com/p/the-trident-and-the-green-ox</guid><dc:creator><![CDATA[Whet]]></dc:creator><pubDate>Mon, 16 Mar 2026 03:12:43 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rHk-!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff672ae68-b2d7-4107-9d9a-38f277491169_736x736.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I&#8217;ve been writing code for a few decades now. Started with C. The kind of C where you know roughly what the CPU is doing at any given moment &#8212; moving a register, touching a block of memory, shaving off a few microseconds. There&#8217;s something satisfying about that directness. Assembly-level intuition. It sticks with you.</p><p>It also makes you a little hostile toward anything that calls itself a &#8220;modern language.&#8221;</p><p>Not because you can&#8217;t learn it. Because it doesn&#8217;t feel right.</p><h2>From C to modern C++</h2><p>For a long time, my C++ was really just C with classes. I found out later that most people who have &#8220;C++ engineer&#8221; on their resume are doing the same thing. That&#8217;s where most of us plateau.</p><p>Then I started using <code>std::vector</code>. Then RAII. Then I ran into <code>compare_exchange_strong</code> and <code>compare_exchange_weak</code> &#8212; spent a full day just figuring out when to use which. Then came C++17, SFINAE, template metaprogramming.</p><p>Honestly, I questioned my life choices.</p><p>But those tools also made my first serious project work the way I wanted it to.</p><h2>50,000 lines of C++, then 3.5 million lines of Python</h2><p>That first project was a bridge layer between a trading platform and a strategy execution service. About 50,000 lines of modern C++, took me six months to write by hand.</p><p>I picked C++ for two reasons: speed, and RAII.</p><p>The results: on Windows 10, it started at around 22MB of memory, then dropped to 11MB after running continuously for a week. On Windows 11, it started at 36MB, settled at 12MB. During all that time it was pulling and processing tick data for every instrument at full frequency.</p><p>Rough around the edges. But the direction was right.</p><p>Later, the product evolved into a web application: AI-assisted strategy editing, multi-user backtesting, a Python backend, and a WordPress frontend. The whole thing took two years.</p><p>The Python backend peaked at 3.5 million lines. WordPress passed 4 million. AI was involved full-time at this point &#8212; I was using Claude 3.5.</p><p>But it was still just a multi-user backtesting system. Plenty of features still missing.</p><h3>A 14-day dead end</h3><p>Claude 3.5 had a habit of breaking things while fixing them.</p><p>One time, the multi-process backtesting module was working perfectly. Then after a round of heavy refactoring, it stopped working entirely. I spent 14 days trying to fix it. Twelve hours a day. Back then Claude didn&#8217;t have the weekly or per-5-hour usage caps yet, so I was grinding pretty much around the clock to make the most of my subscription.</p><p>After 14 days, I gave up. Rolled back to the last stable version. Then manually merged all the other changes from those two weeks, testing each one as I went.</p><p>AI writes fast.</p><p>But when it&#8217;s heading in the wrong direction, it takes you there fast too.</p><h2>Cutting 90%</h2><p>At the end of 2025, I made a decision: cut 90% of the codebase.</p><p>Python backend went from 3.5 million lines to under 500,000. WordPress went from 4 million to under 500,000.</p><p>The system itself was running fine. I didn&#8217;t cut it because it was broken. I cut it because of money.</p><p>AWS bills were brutal &#8212; the system needed multiple servers. Even Claude&#8217;s parent company says it&#8217;ll take two years to reach profitability. OpenAI says five. If the AI companies themselves are getting squeezed by infrastructure costs, a small independent project like mine didn&#8217;t stand a chance.</p><p>I also realized something: users probably want to build their own trading systems on their own machines. They don&#8217;t need me running a massive cloud engine for them.</p><p>So I rebuilt it as a desktop app.</p><p>Without the queue system, the saga orchestration, the multi-user concurrency &#8212; plus two years of backend code to reference &#8212; things moved a lot faster. Started the rewrite on January 2nd, basically finished by mid-February. 500,000 lines of code, six weeks.</p><p>I went back through the git log later and roughly tallied what I&#8217;d deleted from the old system. Ten entire subsystems &#8212; server-side backtesting engine, task queue with priority management, a process manager with its own state machine, real-time WebSocket streaming, a saga orchestrator for failure cleanup, historical data playback, checkpoint recovery for power failures, a standalone cleanup microservice, a cross-service ZMQ communication layer across six dedicated ports, and a session identity context system.</p><p>The saga orchestrator alone had a five-step cleanup protocol: WebSocket recycle &#8594; worker completion wait &#8594; active user cleanup &#8594; test session cleanup &#8594; resource release. The process manager ran its own state machine (STARTING &#8594; RUNNING &#8594; RECYCLING &#8594; STOPPED &#8594; ERROR) with health checks and automatic recovery. The checkpoint recovery system could detect interrupted backtests on server restart by checking MySQL status flags, recover state from Redis, and re-queue everything.</p><p>All gone. Listing it out made me a little dizzy.</p><h2>Claude 3.5 to 4.6</h2><p>Using Claude to write code has been a love-hate relationship.</p><p>In the 3.5 era, it was $100 a month max. When the model got dumb &#8212; I honestly wasn&#8217;t sure whether my rage would destroy my computer first or give me a heart attack first. I seriously considered both outcomes.</p><p>I wrote in to yell at customer support.</p><p>Then I ran into a billing bug: after requesting a refund, the system showed I&#8217;d unsubscribed. Except I hadn&#8217;t. A month later it started charging again. I successfully canceled, tried every other coding tool on the market, realized I still needed Claude, and resubscribed. Successfully canceled again. Got auto-resubscribed anyway.</p><p>Long story short, it didn&#8217;t kill me. I stuck with it all the way to 4.6.</p><h2>A domain name and a new project</h2><p>After gutting the codebase, I tried to register a domain name for the project. Didn&#8217;t get it.</p><p>But that failure got me thinking about something: if in the future everyone is running multiple AI entities, how do those entities discover each other? They need addressable identities. They need to be findable, trustable. They might even need a reputation system to support collaboration. It&#8217;s like Windows 95 and the internet &#8212; before that, regular people didn&#8217;t have an on-ramp to the web. AI entities need that kind of infrastructure layer too.</p><p>So I started <a href="https://github.com/SilverstreamsAI/ClawNexus">ClawNexus</a> &#8212; an identity registry for OpenClaw instances. It discovers AI agent instances on the network, gives each one a persistent name, and tracks capabilities, trust scores, and online status.</p><h3>AI picked the popular choice. The popular choice didn&#8217;t work.</h3><p>By version 0.3, ClawNexus had over 300 unit tests and 5 integration tests &#8212; the integration tests were for multi-node discovery across a WireGuard VPN, with nodes at 10.66.66.x addresses.</p><p>Claude chose mDNS for discovery &#8212; standard practice. But in my WireGuard environment, it kept casually skipping certain cross-machine test cases.</p><p>I sat it down for a serious conversation: why can&#8217;t this supposedly universal protocol handle all the scenarios? It couldn&#8217;t give me a straight answer.</p><p>Here&#8217;s the thing. I have this habit at home &#8212; I set up LAN games of StarCraft with friends. We use IPX-over-UDP via ipxwrapper. And that setup has always worked perfectly over WireGuard.</p><p>So I asked Claude directly: why not use the IPX protocol? It pushed back. Said we didn&#8217;t need it.</p><p>Fine. I made it implement those skipped test cases using IPX anyway.</p><p>That evening:</p><ul><li><p>10:35 PM &#8212; started adding IPX support</p></li><li><p>11:00 PM &#8212; cross-machine tests running</p></li><li><p>11:25 PM &#8212; all cases passing</p></li></ul><p>Afterward I asked Claude to explain why it had originally chosen mDNS over IPX.</p><p>The explanation sounded perfectly reasonable. It just didn&#8217;t apply to the system I was actually running. That was a frustrating moment.</p><h3>300 unit tests weren&#8217;t enough</h3><p>This is a habit from my C days.</p><p>Even with 300+ unit tests all passing, I still went through every command-line parameter by hand.</p><p>Found several that weren&#8217;t doing anything at all.</p><p>Claude 4.6&#8217;s explanation sounded completely correct.</p><p>But I couldn&#8217;t accept it.</p><p>I adjusted my approach after that: I didn&#8217;t just have AI write code and tests &#8212; I baked my manual testing process into its workflow too. The problem never came back.</p><h3>Three days after launch, a copycat appeared</h3><p>Three days after publishing ClawNexus to npm, I stumbled across a GitHub repo with the exact same name on social media.</p><p>This is where Claude&#8217;s breadth of knowledge showed up. It helped me investigate the other project&#8217;s origins, the problems in their implementation, the flaws in their design philosophy. Then in a very short time it helped me shore up every position I needed to hold.</p><p>Getting through all of that alone? No chance.</p><h2>The Trident and The Green Ox</h2><p>Why do the immortals in mythology ride mounts?</p><p>Laozi rode a green ox through Hangu Pass. Guanyin rides a golden-haired lion. The Buddha&#8217;s mount is a six-tusked white elephant. The ox is faster than walking, but it needs someone on top who knows where to go. AI is that ox &#8212; it writes code faster than me, searches information faster than me, analyzes competitors faster than me. But it didn&#8217;t know that mDNS doesn&#8217;t work well over WireGuard. It didn&#8217;t know whether to write or cut 90% of the code. It even managed to run me in circles for 14 days.</p><p>So why does Poseidon also carry a trident?</p><p>Because some situations demand certainty.</p><p>AI sometimes guesses. Same question, different answers. Rephrase it slightly, different answer again.</p><p>Code never does that.</p><p><code>compare_exchange_strong</code> (a C++ atomic operation) &#8212; no matter how many times you call it, the same inputs always produce the same result. C++ template metaprogramming, Python&#8217;s deterministic pipelines, Rust&#8217;s type system &#8212; these are the tridents. Given input, guaranteed output. Where AI is uncertain, they provide precision.</p><p>Think about it: tools like Claude Code and Codex are themselves an ox wielding a trident. AI generates fast, code tools execute deterministically.</p><p>The ox runs. The trident strikes. The rider chooses the direction.</p><p>The world needs the speed of the ox.</p><p>The certainty of the trident.</p><p>And most of all &#8212; the people who can ride one and wield the other, and survive every moment when things fall apart.</p>]]></content:encoded></item></channel></rss>