TRANSCODE Explorations into the Code Transcendental.

A Quarter Inch

John Henry, Paul Bunyan, and a YAML parser

We have all heard the stories…

In Disney’s 1958 short Paul Bunyan, a salesman named Joe Muffaw rolls into the logging camp with a steam-powered saw and challenges Paul to a contest. At the end of the day they measure the timber. Paul’s pile comes to 240 feet. Joe’s comes to 240 feet and a quarter inch. Paul and Babe walk off into the sunset and never come back. John Henry’s story ends worse. He beats the steam drill, but his heart gives out with the hammer still in his hand.

Neither story is history. Paul Bunyan is a tall tale. Folklorists still argue over how much of him came from logging-camp storytellers and how much from a lumber company’s advertising in 1916; one folklorist, Richard Dorson, held him up as an example of “fakelore.” Joe Muffaw is a cartoon. John Henry was probably a real man: the historian Scott Reynolds Nelson found him in Virginia prison records, a young Black convict leased out after the Civil War to drive steel in a railroad tunnel. Nelson thinks he died of silicosis from the tunnel dust, not with a hammer in his hand.

But these contests come down to us through ballads, not the contested history. We tell them as tributes to the spirit of man, and they are. But I’ve always heard them as stories about the machine. John Henry won once, and it killed him. Paul lost by a quarter inch, and a quarter inch was all the steam saw needed, because tomorrow it will be a foot.

I’ve been thinking about those two stories again since October 20th.


Ineligible

NLnet is one of the best friends open-source infrastructure has. It gives first grants of €5,000 to €50,000, mostly European Union money, to people building the plumbing of the internet. I was considering applying for one for Oyl, my YAML library (YAML being the configuration format behind Kubernetes, GitHub Actions, Ansible and a great deal else), when I read version 2.0 of NLnet’s policy on generative AI.

AI may no longer be used to write a proposal (there’s an exception for accessibility), and that ban “includes LLM generation of ideas, as well as restructuring, shortening and translation.” Inside a funded project, “it is not allowed to use generative AI for producing artefacts of any kind, including code, design, and documentation.” An AI may read your code and point out flaws, but you have to write the fixes yourself. The FAQ is blunter. Asked whether using AI as a “coding partner” makes a project ineligible, NLnet answers: “The short answer is yes.”

That’s me. The AI-written code already in Oyl apparently wouldn’t rule it out: NLnet allows that, as long as the application says so. What rules Oyl out is how I work. Every line the grant paid for would have to be written by hand, and that isn’t how Oyl was built or how I’m going to continue to build it.

I want to be fair to NLnet. In its announcement, its director of strategy, Michiel Leenaars, calls the policy “first and foremost a pragmatic measure towards self-protection.” AI brought “an avalanche of additional proposals lacking maturity and relevance,” and NLnet’s reviewers were buried. He says NLnet is “not trying to make a more general point about quality,” and I believe him. Funders are drowning. But he does make one specific point: that “for our particular domain of digital infrastructure and at this point in time, the actual yield turns out to not be worth the additional effort.”

Oyl is digital infrastructure. So let me tell you how it came to be and what it yielded, and then make the claim I expect a lot of people will dislike: Oyl would not exist without AI. Not because no human could write it. Given enough people and enough years, someone could. But nobody would have, least of all me. And the gap between what one person can build alone and what one person can build with AI is going to keep growing, until, for fully optimized and secure software, there’s no other practical way.


The bug I gave up on

I discovered YAML around 2002. It was a year or so old, and its spec was still a working draft; version 1.0 wasn’t final until January 2004. I devoured that draft, and I thought it was grand.

In September 2002 I joined the yaml-core mailing list, where the spec was being worked out, and for a couple of weeks I posted constantly. I kept coming back. In 2004 I was in the thick of the design arguments for YAML 1.1, mostly about tags, and in 2006 I joined the discussions of what YAML 1.2 should be. The spec has three authors: Oren Ben-Kiki, Clark Evans and Ingy döt Net. For a brief time, I felt like the fourth wheel on that team.

I’ve wanted a better YAML library for a long time. In 2011 I opened an issue on Psych, Ruby’s YAML library, asking it to stop throwing away tags it didn’t recognize. It’s still open. In early 2013 I forked Psych and spent six days adding schemas, so that a program could decide which tags map to which classes instead of everyone sharing one global table. Sixty-three commits. While I was at it, I asked on the yaml-core list how tag resolution was meant to work. Oren Ben-Kiki answered that an application “is allowed to define any mapping it wants between tags and native types.” That was the whole idea of the fork.

My fork mostly worked. One test failed, and I couldn’t work out why. I offered the work upstream anyway, half hoping the maintainer would be impressed enough to help me find that last bug. The answer, reasonably, was no: someone would have to maintain it, and it wasn’t clear anyone needed it. Saying no is a maintainer’s job, and I don’t hold it against anyone. I recall at the time, one of YAML’s creators had hoped I’d help with some development work he had in mind. I wanted to help, but in the end I didn’t have the time for that either. And so the fork sat.

I can write this stuff. It’s just hard, and hard takes hours, days, weeks and months—time I just didn’t have.


Thirteen years later

Last winter I wanted a YAML 1.2 parser for Crystal, the language I do much of my work in now. Crystal’s standard library wraps libyaml, which implements YAML 1.1. So I did my usual math. A conformant YAML parser is a big job. A fast one is a bigger job. If it were just me, it wasn’t in the cards.

But it wasn’t just me anymore. I asked an AI the questions I knew to ask. Is this plausible? Could we use SIMD to make it fast? (SIMD: look at sixteen bytes at a time instead of one.) How feasible is it, really? The answers were reassuring, and two facts made me believe them. YAML has a precise spec, and it has an official test suite of 402 cases. A project with a spec and a test suite can check its own work.

So I challenged the agent to give it its best shot.

I had never seen an agent take something on like that. Usually, twenty minutes in, I get questions: this needs deciding, that needs deciding. This one, as I remember it, ran for about four days and barely made a peep. The first commit landed on February 7th: 4,641 lines, with a SIMD scanner, a parser, an emitter and a test-suite runner, co-authored by Claude Opus 4.6. Two days later, version 0.3.0 passed 396 of the 402 cases. (The other six have no expected output in the suite itself.)

The morning after that first commit I asked a different AI, OpenAI’s Codex, to review it. My exact words were: “I vibe coded a new YAML scanner, parser, emitter in C.” I’ll own that. On day two after the first commit, that’s exactly what it was. Everything after day two is why I’m writing this.


What the steam saw cut

That was February. Here’s Oyl at version 1.4, eight months later:

  • Correct. It produces the expected output for all 308 valid cases in the YAML Test Suite and rejects all 94 invalid ones.
  • Fast. It parses real-world files 4 to 12 times faster than libyaml, the C library most languages’ YAML support is built on. It’s also faster than libfyaml and rapidyaml, two newer high-performance parsers, on all 12 inputs in its benchmark. (All four are measured as event parsers, with rapidyaml in its fastest mode; the README has the numbers and the method.)
  • Compatible. Its YAML-to-JSON output matches Kubernetes’ own converter, sigs.k8s.io/yaml, byte for byte, about seven times faster. Dropped into a build of Helm, it took helm pull on a 64 MB repository index from 5.7 seconds and 1.4 GB of memory to 1.5 seconds and 0.6 GB, with identical output.
  • Hardened. A fuzzer has thrown more than 13 billion inputs at it under AddressSanitizer and UndefinedBehaviorSanitizer. Its hash tables are keyed with a secret, so crafted input can’t flood them, and one test makes every memory allocation fail in turn.
  • Flexible. It reads YAML 1.1 and go-yaml’s dialect as well as 1.2, and it can rewrite a YAML 1.1 file in place so it means the same thing under 1.2, keeping every comment.
  • Shipped. Debian, Arch and RPM packages, a Rust crate, a Go module and a Crystal shard, tested on Linux, macOS and Windows.

The git history shows 225 commits to the C library on 31 different days. Claude is credited as co-author on 222 of those commits. The other three are merges. I didn’t keep a timesheet. On those 31 days, the time from each day’s first commit to its last adds up to about 235 hours, and some of that was the agent working while I wasn’t. Counting only the time my own attention was on Oyl, it comes to at most a few hundred hours.

The last stretch of that speed is where it got interesting. Getting there meant reading the CPU’s performance counters, sampling instruction pointers with PEBS, catching GCC copying an 80-byte token with a microcoded rep movsl instruction, tracking down store-forwarding stalls that swung timings 10 to 18 percent after unrelated edits, and building hot functions at sixteen different code placements to tell a real 2 percent gain from layout noise. That’s the work that separates a fast library from the fastest one, and almost nobody does it by hand at that scale, because it’s ruinously slow. It’s what I mean by fully optimized.


Possible is not practical

Could a person have built Oyl? Yes. Here’s how long it has taken others to build YAML libraries:

Library Language Began Lead author’s commits
libyaml C 2006 91 of 228
yaml-cpp C++ 2008 722 of 1,098
rapidyaml C++ 2018; version 0.1.0 in late 2020 1,938 of 2,093
libfyaml C 2019 or earlier; its first public commit already had 33,000 lines 1,665 of 1,800
Oyl C February 2026 225, on 31 days, with Claude

rapidyaml is the fairest comparison: one dedicated author, built for speed, almost three years to version 0.1.0. Oyl beats its event parser on every benchmark input. libfyaml is the counter-example, and it deserves its due. Pantelis Antoniou wrote a YAML library in C that passes the entire test suite, by hand and almost entirely alone. It also does some things Oyl doesn’t, like editing documents and loading YAML straight into C structs. It took him years. These are good ideas and I will probably add some of them to Oyl too. But it won’t take years, just days.

The old COCOMO cost model, the one tools like scc print, puts Oyl’s 34,000 lines of code, tests and bindings at about 97 person-months: seven people for fourteen months. That’s about 14,700 working hours, against my few hundred. It’s a crude yardstick from 1981. But it’s a fair guess at what Oyl would have cost by hand, and a price I certainly could not have paid.

That’s what I mean by possible but not practical. Not never. Just not by me, on my own dime. And I doubt anyone else would, either. Exceptional programmers like libfyaml’s Pantelis Antoniou and rapidyaml’s Joao Paulo Magalhaes are exactly that: exceptional, and they spent years on theirs.


A quarter inch

While writing this post, I went back to the 2013 fork. I’d forgotten I ever pushed it, but it’s still on GitHub, under my trans account. Claude set up Ruby 1.9.3 in a container and ran my branch’s tests side by side with upstream Psych at the commit I’d forked from. Upstream ran 504 tests with no failures. My branch ran 514 and failed exactly one: a !float 12 was loading as the integer 12. In a refactor on January 31, 2013, I had accidentally removed the line that mapped the old !float shorthand to Float, and the schema that replaced it never got the tag back.

The fix was one line. While we were in there, we fixed the two tests I’d skipped with notes to myself. One of those notes had the diagnosis exactly right; I’d just never found the cure. Now the branch runs its 514 tests with no failures, and the only test it skips is one upstream skips too. The fix went in with an epitaph for a commit message:

Here lies the !float bug.
Born 31 January 2013, in a refactor that meant well.
Died 31 October 2026, of one line, thirteen years and nine months to the day.
It kept this branch a quarter inch from the finish.
Rest in peace.

I want to be straight about what this does and doesn’t prove. Finding a bug that a failing test points straight at, in code that already exists, is much easier than writing the code. On its own it proves nothing. It’s a parable. In 2013 I was Paul: I did nearly all the work by hand, came up a quarter inch short, and nobody had the time to find that last quarter inch, least of all me. In 2026, I had help that didn’t need to be talked into it.


Objections

I went looking for the case against me. Here it is.

“AI makes developers slower.” The study everyone cites is METR’s 2025 trial, in which sixteen experienced open-source developers were 19 percent slower with AI tools while believing they’d been 20 percent faster. It’s a good study, and that gap between belief and measurement is a real warning. But it tested early-2025 tools on two-hour tasks in large codebases the developers already knew well. METR ran a larger follow-up in 2026 and found developers faster, though not by a statistically clear margin, and it thinks the real effect is bigger: 30 to 50 percent of its developers held back tasks they didn’t want to do without AI. METR calls its estimate “a lower-bound on the true productivity effects.” And Oyl was not a two-hour task.

“AI-written code is worse.” A study of open-source projects that adopted Cursor found the speed gains faded while static-analysis warnings and code complexity rose and stayed up. Veracode found security flaws in about 45 percent of AI-generated code samples. I believe both. But most code doesn’t have what Oyl has: an external spec, 402 conformance cases, benchmarks against every competitor, and 13 billion fuzzer runs. Quality doesn’t come from whoever typed the code. It comes from whatever checks it.

“It only works when there’s a spec and a test suite.” Largely true, and it’s an important lesson I have learned. Chris Lattner put it well after studying the C compiler Anthropic built with a team of AI agents: “Current AI coding systems excel when success criteria are clear and verifiable: compile the program, pass the tests, improve performance.” The steam saw cuts best along a chalk line. But look at what has chalk lines: parsers, compilers, codecs, protocols, file formats, databases, kernels. That’s most of the infrastructure the rest of software stands on, and exactly the kind of thing NLnet funds. Anthropic’s compiler was checked against GCC for correctness, not for speed, and by its builders’ own account its output is less efficient than GCC’s with every optimization turned off. Oyl was measured against every competitor, and it’s fast. Give the machine a measuring stick and it will use it.

“It’s just regurgitating its training data.” Lattner says of that compiler that “LLVM and GCC code are clearly part of the training set,” and I’m sure Oyl owes something to libyaml and the others. Oyl also had the advantage of coming second: the test suite, the benchmark files and the documented mistakes of every library before it. Second movers have always had that advantage. But Oyl is faster than all three libraries it’s measured against, so it isn’t a copy of any of them. The question isn’t whether it’s original. It’s whether it’s better. That’s simply the nature of progress. Feel free to measure it.

“Then nobody owns it.” The U.S. Copyright Office says purely AI-generated material can’t be copyrighted, and NLnet held a webinar on exactly this question. I’m not a lawyer. But Oyl isn’t “purely” anything. I chose the project, set the requirements, judged the results, and decided what to measure and when to stop. When choices had to be made, I weighed the pros and cons and made the call. I steered it for eight months.

“Funders can’t wade through a flood of slop.” True, and NLnet’s problem is real. A ban on AI-written proposals answers it. A ban on AI-written code inside funded projects answers a different question, and I think it gets the answer wrong. It funds the hammer and turns away the saw.


The Gap

Paul’s problem wasn’t the quarter inch. It was the next day.

The work AI agents can do on their own keeps getting longer. METR measures it as a “time horizon”: how long a task an agent can finish half of the time, counted in the hours it would take a skilled person. That number keeps doubling: about every six and a half months over METR’s whole record, and about every three months since 2024. By last May, METR reported that the best models had reached horizons of about 12 to 20 hours, a couple of working days for a person, and that its test suite “can’t reliably measure time horizons above 16 hours.” The ruler ran out.

You can see it in a single step, too. In April, Epoch AI and METR published MirrorCode, a benchmark in which agents rebuild a program from its tests and a working binary, without the source. On gotree, a 16,000-line Go program that experts estimated at two to seventeen weeks of human work, Claude Opus 4.5 passed 63 percent of the tests. Opus 4.6 passed 2,000 of 2,001. That’s the model that wrote Oyl’s first commit. When I said I’d never seen an agent take something on like that, it wasn’t just me. Something crossed a line last winter.

Machines are also starting to find optimizations people missed. Google says its AlphaEvolve agent found a scheduling heuristic that recovers 0.7 percent of its worldwide computing capacity, and sped up a key kernel in Gemini’s architecture by 23 percent.

Now set that beside what full optimization takes. It’s a search: memory layouts, instruction sequences, SIMD widths, branch placement, compiler quirks, every change measured against noise. People do it by hand only for the hottest code in the most famous libraries, because a person can only try a handful of variants a day at best. A machine that can try thousands, and measure every one, makes full optimization the default rather than the exception. Software built that way will run faster and cost less than software that isn’t. When the difference is a quarter inch, you can ignore it. When it’s four to twelve times, and growing, the market won’t.

Security is going the same way. In 2024, AI-written fuzz tests found a bug in OpenSSL that had probably been there for twenty years, in projects that had already been fuzzed for hundreds of thousands of hours. This February, Anthropic reported that Opus 4.6 had found more than 500 high-severity vulnerabilities in open-source code, some of them missed for decades. Attackers have the same tools: in 2025, Anthropic says, a state-sponsored group used Claude to do 80 to 90 percent of the work of an espionage campaign. Defenders are answering in kind. Google says its Big Sleep agent found a SQLite flaw that only attackers knew about, in time to stop them using it. I’ve seen it in my own work: with AI’s help I’ve found more security holes in my code than I knew were possible. When the people attacking your code have AI, checking it by hand won’t keep up.

So here’s my prediction, and the part I expect people to fight me on: the fully optimized and secure systems of the next decade won’t be practical to build by hand. Not impossible. Just not practical.


Which story

John Henry won, and died. Paul lost by a quarter inch and walked away. We tell those stories as tributes, and we should; the achievements of man are magnificent. But nobody tells it as Joe Muffaw’s story, and Joe was a man too (albeit an archetype of one). He was just a man with a machine.

I tried being Paul in 2013. I’d rather be Joe.

If you think I’m wrong, it’s all open source. Run the benchmarks (make bench-compare), run the test suite, run the fuzzer, and tell me what you find.


Claude helped me gather the evidence for this post and draft it. The story and the opinions are mine, and so are any typos.

If you’d like help putting Oyl to work, I offer that through my company, Tab Computing: tabcomputing.com/yaml.