Abstract
This report follows Alera builds a library factory, which covered the factory’s first four runs up to 23 October 2026. Between 23 and 27 October the same factory, made of specialist agents, a shared process and a fixed architecture, took five more projects to 1.0:
- onefont-csharp, fonts and text shaping, on 23 October;
- oneaudio-csharp and oneshader-csharp, audio and an HLSL compiler, on 25 October;
- onegame, a game engine with no editor, on 26 October;
- onehtml-csharp, HTML, CSS and accessibility checking, on 26 October.
In the same days onepdf-csharp went from a read-only 1.0 to 1.11.1, adding editing, forms, signing, PDF/A, PDF/UA and a layout package. oneimage-csharp went to 1.10.2. oneocr-csharp, which the first report announced as the fifth run, is still in its accuracy push and has not been released.
The runs no longer took turns. Build agents for up to six projects were active in the same hour on 24 October, and for up to nine on 26 October.
Owner attention is measured more strictly here. A message counts only when Kurtis corrects or steers the work: direction, scope, a fix, a decision. Status checks and instructions to carry on don’t count. On that measure the first four runs took 61, 65, 8 and 8 steering messages. The new runs took:
- onefont-csharp: 0. A project manager agent decided to create it;
- onegame with oneshader-csharp and oneaudio-csharp: 30, most of them Kurtis answering the engine’s design interview himself;
- onehtml-csharp: 16;
- oneocr-csharp: 15 so far.
The main findings:
- Steering per run stopped falling when the work changed kind. The library that grew out of an existing one took none. The engine took more than any run since the second, because Kurtis chose to make its design calls himself (section 3).
- Parallel runs moved the owner’s attention more than they added to it. Of the 241 messages he sent to the open-source projects’ agents in these four days, 88 went to the runs covered here. 73 went to sessions exploring new ideas. On the evening of 26 October he capped the number of builds running at once (section 5).
- Every library still faced outside checks; the engine faced fewer. oneaudio-csharp, oneshader-csharp and onehtml-csharp each have an outside suite, a benchmark against the incumbent, fuzzing and published losses. onefont-csharp has no published speed benchmark. onegame has outside references and fuzzing, but no benchmark against another engine and no published losses (section 7).
1. The runs in one table
Each row runs from Kurtis’s first message in the conversation that started the build to its 1.0 release. The first four rows are the runs of the first report, recounted.
| Run | Project | First message → 1.0 | Steering messages | All messages | Clock hours with steering |
|---|---|---|---|---|---|
| 1 | oneyaml-rust | 9 d 5 h | 61 | 112 | 22 |
| 2 | oneyaml-go and oneyaml-csharp, with oneyaml-kit | 3 d 21 h | 65 | 108 | 20 |
| 3 | oneimage-csharp | 22 h 56 min | 8 | 14 | 4 |
| 4 | onepdf-csharp | 17 h 27 min | 8 | 11 | 3 |
| 5 | oneocr-csharp | Not released (4 d 3 h by 27 Oct, 10:10) | 15 | 35 | 8 |
| 6 | onefont-csharp | 3 h 11 min, first commit to 1.0 | 0 | 0 | 0 |
| 7 | onegame, oneshader-csharp, oneaudio-csharp | 1 d 22 h (oneaudio-csharp 19 h 53 min, oneshader-csharp 20 h 27 min) | 30 | 34 | 7 |
| 8 | onehtml-csharp | 1 d 0 h 36 min | 16 | 19 | 4 |
Notes on the table:
- 1.0 is the v1.0.0 git tag, or the crates.io publish for oneyaml-rust, as in the first report. Times are US Central.
- onefont-csharp had no owner message to start from. Its row gives the time from the repository’s first commit to the tag.
- Run 7 is one planning conversation that produced three projects. Its row runs to the last of the three tags, onegame’s.
- “All messages” is the first report’s measure, applied to the new runs for comparison. Section 2 explains the difference.
Agent runs and cost, counted up to each 1.0 (oneocr-csharp up to 27 October, 10:00):
| Project | Agent runs | Metered-equivalent cost |
|---|---|---|
| oneocr-csharp | 166 | ~$1,220, still running |
| onefont-csharp | 2 | ~$8 |
| onegame, with its planner | 75 | ~$570 |
| oneshader-csharp | 28 | ~$205 |
| oneaudio-csharp | 24 | ~$166 |
| onehtml-csharp, with its planner | 64 | ~$444 |
In every run Claude Sonnet 5.5 ran the engineers, and Claude Opus 5.5 the planners, orchestrators and project managers. Every model ran through a subscription, so the recorded spend is $0. The costs are what the same tokens would cost at list prices. They leave out the project manager agents shared between projects. oneocr-csharp also spent $96.66 of real money generating receipt photos for its test and training data, by its agents’ own ledger.
2. How owner attention is counted now
The first report counted every message Kurtis typed into a library’s agent conversations between his first message and its 1.0. That count is kept as published: 112, 108, 14 and 11.
This report counts steering messages only. Kurtis set that rule when he commissioned it. Each message found by the first report’s method (stored conversations, attribution by elimination, a hand read) was read again and given one of four codes:
- Steering: it corrects or steers the work. That covers a direction, a scope change, a fix, a decision, or an answer to a design question, a one-letter one included.
- Check-in: status checks, such as asking where the build stood or how close it was to 1.0, and instructions to proceed or to keep waiting on an agent.
- Question: a request for information that doesn’t direct the build, such as asking what serde is.
- Setup: a restart, an account, a credential, a device to plug in.
Only steering counts. The two measures, run by run:
| Run | All messages | Steering | Check-ins | Questions | Setup |
|---|---|---|---|---|---|
| 1 · oneyaml-rust | 112 | 61 | 30 | 18 | 3 |
| 2 · oneyaml-go, oneyaml-csharp, oneyaml-kit | 108 | 65 | 25 | 13 | 5 |
| 3 · oneimage-csharp | 14 | 8 | 1 | 2 | 3 |
| 4 · onepdf-csharp | 11 | 8 | 1 | 2 | 0 |
| 5 · oneocr-csharp (so far) | 35 | 15 | 13 | 6 | 1 |
| 6 · onefont-csharp | 0 | 0 | 0 | 0 | 0 |
| 7 · onegame, oneshader-csharp, oneaudio-csharp | 34 | 30 | 1 | 3 | 0 |
| 8 · onehtml-csharp | 19 | 16 | 1 | 1 | 1 |
The strict measure removes most of what the factory later took over: the check-ins and waits of the first two runs, 55 messages between them. On the strict measure the first four runs go 61, 65, 8 and 8, which is still a big drop. It also changes what a high count means. The 30 for run 7 are almost all decisions, not supervision.
The coding is one reader’s judgment. The rules are above, and every message’s code is in the verification record. A one-letter answer counts the same as a 2,500-character correction. Neither measure counts the time Kurtis spent reading.
3. Runs 5 to 8
3.1 Run 5: oneocr-csharp, still in its accuracy push
Kurtis asked on 22 October whether a decent OCR library for .NET could run locally without a heavy model. At 06:47 on 23 October, four minutes after onepdf-csharp’s 1.0, he sent the go-ahead. The project manager answered a 45-question planning interview, and the repository’s first commit came at 07:48.
Since then the record shows:
- A second approach, started and dropped. On 23 October Kurtis had a second design, one that recognizes each glyph shape once per page, planned as a parallel fork and treated as an experiment. He dropped it the next afternoon, and its best ideas went into oneocr-csharp as extra stages.
- A higher bar. In the same message he raised the target from beating Tesseract to the best local engine in every category: “I don’t want to just barely beat Tesseract where tesseract sucks. We’re going for the absolute best quality we can get.”
- A rule an agent invented. An agent-written rule kept model-labelled data out of shipped weights. On 25 October Kurtis overrode it for receipts: “that was not my rule. Some agent made that up.”
- A sealed benchmark that didn’t hold the earlier ranking. By the project manager’s report on 26 October, the sealed test set put oneocr-csharp behind the leader, PaddleOCR or Apple Vision, on character error in every category. It was ahead of Tesseract on nearly every row and won reading order on layout and screenshot pages. An earlier second place had come from a development set the agents had tuned on. Kurtis chose to keep the bar and push accuracy rather than ship with the table as it stood.
On 27 October the production recognizer’s training run is approved and waiting its turn on the shared GPU. One decision on training data is open with Kurtis. The repository is private, with 358 commits and no release.
The run drew more check-ins than any other since the first two: 13 of its 35 messages, most of them asking for the latest rankings.
3.2 Run 6: onefont-csharp, created by an agent
At 16:51 on 23 October Kurtis asked for a fluent layout layer in onepdf-csharp. The project manager ran the planning interview in his place. Three minutes later it ruled on the architecture question itself. The layout layer needed real text shaping, and oneimage-csharp already had that code, so the shaping moved into a new shared library rather than into a third copy. Kurtis sent nothing about onefont-csharp, and his only other message on the layout work was “I’m not making the layout call. You figure it out.”
The onepdf-csharp team built it. The first commit came at 18:52, and v1.0.0 was tagged at 22:03 and was on NuGet a minute later: 3 hours 11 minutes, in two engineer runs, about $8 at list prices. The speed comes mostly from the port. The 1.0 scope was oneimage-csharp’s own text code, moved and given its own API. By noon the next day oneimage-csharp 1.10.0 had moved its own text package onto it.
3.3 Run 7: onegame, oneshader-csharp and oneaudio-csharp
The run began with a question to a planner at 14:07 on 24 October:
How much work would it be to write a full game engine in c#? Essentially a competitor to Godot, but c# native, with more features and better performance. Importantly, though, I want *no* IDE at all. The idea here is that it’s purely agent-driven.
The planner surveyed Kurtis’s existing games. He sent 7 messages on direction: servers in C#, which platforms matter, a client-server sync framework, and a note that the planner had gone too far into detail. Then he answered the design interview himself, in 19 messages from 15:24 to 16:10, 18 of them steering. The engine’s design record carries 40 decisions marked as his and none marked as a project manager’s. One of his answers made the shader compiler and the audio library standalone projects, built alongside the engine. Another chose HLSL as the shader language because agents know it best.
A project manager took over at 17:09 and started three build orchestrators at 17:11. From there Kurtis sent four steering messages before the releases:
- a go for the first game’s planning and for publishing oneshader-csharp previews;
- “I don’t want to answer any of the trader questions - you answer”, about the first game to be ported;
- the next morning, a go-ahead for all of it and for making oneaudio-csharp and oneshader-csharp public, plus a list of the devices he owned;
- the go to tag onegame 1.0, on 26 October.
oneaudio-csharp was tagged at 10:01 on 25 October and oneshader-csharp at 10:35, 16 h 37 min and 17 h 18 min after their first commits. onegame was tagged at 12:28 on 26 October.
3.4 Run 8: onehtml-csharp
onehtml started as an idea written up on 22 October, during the oneimage-csharp run. Kurtis opened its planner at 14:24 on 25 October, with the scope taken from another of his projects.
Most of the run’s steering went into one correction. Kurtis asked a project manager to run the planning interview. The manager told the planner to shorten its questions and handed it the whole post-interview plan. He stopped it, objected, and started fresh managers with the same brief. Five managers were started in 26 minutes, and by his own messages he stopped four. To the planner he wrote: “ALWAYS ask one question at a time, nothing more. NEVER batch the questions or shorten them.” Ten of the run’s 16 steering messages belong to that half hour.
The build started at 15:47, with the first commit a minute later. Kurtis made two more decisions: whether three of the checker’s suggested fixes stay private to the project that asked for them, and making the repository public. v1.0.0 was tagged at 15:00 on 26 October, 24 hours 36 minutes after he opened the planner.
4. After 1.0: onepdf-csharp and oneimage-csharp
Both libraries kept growing while the new runs went on. onepdf-csharp went from 1.0 to 1.11.1 in 3 days 23 hours.
| Library | 1.0 | Latest on NuGet | Releases after 1.0 | Commits after 1.0 | Library C# lines, 1.0 → latest |
|---|---|---|---|---|---|
| onepdf-csharp | 23 Oct, 06:43 | 1.11.1, 27 Oct | 15 | 206 | 40,024 → 106,305 |
| oneimage-csharp | 22 Oct, 11:00 | 1.10.2, 26 Oct | 13 | 175 | 49,507 → 133,494 |
onepdf-csharp’s releases, from its changelog:
- 1.1–1.3, 23 October: appearance generation, editing and saving, form filling, page operations, merge and split.
- 1.4–1.6, 23 October: signing and signature verification, PDF/A output, true redaction, better reading order on multi-column pages.
- 1.7–1.10, 24 October: the fluent layout package on onefont-csharp, PDF/UA, Knuth–Plass line breaking.
- 1.11, 26 October: tagging of existing untagged PDFs. Kurtis passed on that request from another of his projects at 18:10. Work began at 18:27, and 1.11.0 was tagged at 19:34.
oneimage-csharp added drawing, text, layers and Photoshop fill layers, an internal JPEG 2000 decoder for onepdf-csharp’s rendering, and a region cache. Its text package moved onto onefont-csharp in 1.10.0.
Kurtis steered this growth with five messages. One was a caution against defining the PDF render gate by agreement with one reference renderer: “Is PDFium 100% right all the time?” The others were the layout layer, the layout delegation, the tagging request, and, on 24 October, declaring onepdf-csharp done.
5. Parallel runs: what they cost the owner
Between 23 October, 06:43, and 27 October, 10:10, Kurtis sent 241 messages to agents working on the open-source projects, in 39 clock hours.
| Went to | Messages | Steering |
|---|---|---|
| The runs in section 3 | 88 | 61 |
| Idea sessions: new libraries, a separate research project | 73 | 0 |
| Planning oneecma, onerender and onearchive, whose builds started on 26 October | 39 | 29 |
| Libraries after their 1.0 (section 4, onegame devices) | 28 | 6 |
| Posts about the work | 10 | 0 |
| Process rules across projects, other | 3 | 1 |
The idea sessions are coded as questions, because they don’t steer a build. They are where most of his messages went on 24 October, his busiest day, with 103 messages.
The build agents were busy in parallel. These are the projects whose agents made at least one model call in a given hour:
| Day | Most projects in one hour | Median |
|---|---|---|
| 23 Oct | 3 | 2 |
| 24 Oct | 6 | 3 |
| 25 Oct | 5 | 3 |
| 26 Oct | 9 | 2 |
The three projects planned on 26 October are oneecma, an ECMAScript interpreter built around its error reports; onerender, an HTML and CSS layout and rendering engine; and onearchive, compression and archives. Their builds started at 17:15, 17:22 and 19:46 that day, and all three were among the nine projects active in each hour from 20:00. The onearchive planning session also planned two projects that are still queued.
What the record shows parallel work costing him:
- Managers talking to agents while he waited. A manager passed a point to its build orchestrator while Kurtis was still discussing that point with the manager, and he told it to stop acting on discussions before they were settled. Another left him waiting while it handled messages from its own agents.
- Check-ins on the run that wasn’t converging. 13 of oneocr-csharp’s messages were status checks. Run 7 and run 8 had one each.
- Hands-on setup. 13 messages on 26 October went to connecting a Steam Deck, an iPad, an Android phone, a controller and a Windows laptop so onegame could be checked on them.
- A limit he set. At 19:29 on 26 October, with four builds in flight (oneocr-csharp, onerender, onepdf-csharp and oneecma), he told the project manager not to start new ones until one finished: “Perhaps we should just set up a queue system and move projects around in the queue as they progress, so that we don’t have too many going at once”. The queue now holds four active builds.
The shared second machine became a queue of its own. Benchmarks, fuzz campaigns and GPU training from several projects took turns under a lock, and its rules changed three times on 23 October (section 6).
The devlog records client work on 23 and 26 October, 30 and 55 tasks, and none on 24 and 25 October.
6. Refining the factory with no gap between runs
In the first report, each refinement came between a result and the next go-ahead. Here there was no between: every run started while others were building. oneocr-csharp started four minutes after onepdf-csharp’s 1.0. onefont-csharp, run 7 and run 8 each started while two other projects were building. So the refinements went in mid-run, mostly within minutes of the message that prompted them.
| When | What prompted it | The change | Lag |
|---|---|---|---|
| 23 Oct, 07:32–14:06 | GPU training and benchmarks from several projects on the second machine | Three rules for the shared machine: the GPU listed, the benchmark lock claimed inside the job, GPU jobs in resumable chunks of two hours or less | Same day |
| 24 Oct, 16:58 | Kurtis drops the second OCR approach | Its ideas become stages in oneocr-csharp | Same message |
| 25 Oct, 14:53 | Kurtis objects to a manager shortening a planner’s interview | The project manager’s prompt gets the correction, with his words, at 14:57. A line added on 17 October, which told managers answering for him to keep questions short, is removed at 15:03 | 4 and 10 min |
| 26 Oct, 17:26 | Kurtis sets what counts as a heavy job: more than 8 CPUs, more than 30 minutes of CPU-bound work, any GPU job, any benchmark | The shared machine’s rules | Same minute |
| 26 Oct, 18:49 | Kurtis: every library gets a low-level API and an opinionated happy path built on it | Recorded first in onepdf-csharp at 18:55, now in every project’s README | 6 min |
| 26 Oct, 19:29 | Kurtis: too many builds at once | A build queue with four active builds | Same evening |
One refinement undid an earlier one. The 17 October review told managers that answer a planner’s interview for Kurtis to keep the questions short. On 25 October that shortcut produced the onehtml-csharp correction, and the line came out.
The prompt edits of 25 October are dated by file time; they were not yet committed on 27 October.
7. The outside checks
The first report held each library to four kinds of outside check: a suite or corpus it didn’t write, a benchmark against the library people use, fuzzing, and published losses. The figures below are from each repository at its v1.0.0 tag.
| Project | Outside tests | Against the incumbent | Fuzzing | Published losses |
|---|---|---|---|---|
| onefont-csharp | Unicode 17 line-break, grapheme and bidi conformance files in full. 1,042 shaping cases against SixLabors.Fonts 2.1.3, used as a black box. | Agreement only; no speed benchmark published | One target, 600 s, 1.84 million executions, clean (agents’ record) | Every deliberate difference from SixLabors.Fonts listed with its reason; what isn’t included |
| oneaudio-csharp | RFC 8251 Opus vectors 12 of 12; Opus encoding 269 of 269 configurations byte-identical; FLAC 64 of 64 bit-exact; MP3 11 of 11 within ISO 11172-4 limits; EBU loudness cases | Faster than NVorbis, Concentus and NAudio.Flac on every row, and than NLayer on all comparable rows | Six targets, 660 s each, 0 crashes | MP3 decoding 2.5–2.6× slower than native mpg123 on stereo. The NAudio resampler is 14% faster than the default high-quality mode. |
| oneshader-csharp | spirv-val, naga and Apple’s Metal compiler. Every corpus shader run on the GPU next to the same shader compiled by DXC. | As a NativeAOT binary, about 2.4× faster than DXC on the corpus | Five targets, 600 s each, 0 findings | As an ordinary .NET process, about 6× slower than DXC (14× with the JIT). SPIR-V 5.7% larger by default. Memory not measured. |
| onehtml-csharp | html5lib-tests; WPT selectors 2,537 pass, 43 known failures; WPT accessible names 1,297 pass; all 37 approved ACT rules | Parses 2.74× as fast as AngleSharp 1.8.6, with less memory. Trees identical to AngleSharp’s on 89.98% of 13,857 pages. | Tokenizer and tree builder, 7.0 and 2.7 million executions, 0 crashes; edit fuzzing clean (agents’ record) | Known failures listed per suite; every AngleSharp difference has a documented cause; what it does not do |
| onegame | Khronos glTF sample models against reference renders, and UI layout against headless Chrome (agents’ record) | None | Core and glTF fuzz targets, with regressions in the tests | No losses section |
The incumbent comparisons are the agents’ own measurements, with the method in each repository. They were not re-run for this report.
The checks held for every library. They were not written for an engine. There is no outside suite for “a game engine”, and nothing in the record compares onegame with Godot or another engine on speed or memory.
8. onegame and the claim that the approach works beyond libraries
The first report closed with Kurtis’s view that Alera can set up the same combination of agents, process and architecture for other kinds of work. onegame is the first run that isn’t a library port. What the record shows, kept apart from interpretation:
- It shipped as a product, not a package. At 1.1.0 it was a command-line tool, an SDK and 26 engine libraries, with three sample games. By 1.5.1 it was 29 NuGet packages.
- The 1.0 tag couldn’t be used from NuGet alone. A game’s build still came from a checkout of the repository. Kurtis asked an hour after the tag, “why can’t they be built from nuget packages alone? what’s missing?” The first NuGet release is 1.1.0, tagged 2 hours 13 minutes after 1.0.
- The owner was needed for the design and for hardware. He answered the design interview, and he connected the devices. The samples then passed on a Steam Deck, an Android phone and an iPad on 26 October, after the tag. Before that, the mobile targets had run only on an emulator and a simulator. A check on real Windows audio was still waiting on 27 October.
- It had eight more releases in 18 hours, adding 2D drawing, input actions, an asset service, tweens, particles, saves, a debug overlay and an examples gallery.
- The first game being ported, Trader, runs on the engine but has not shipped.
The rest of this section is interpretation. The engine ran through the same factory, and it reached a working 1.0 in under two days. It did so with more of the owner’s design attention, without the incumbent benchmark that keeps the libraries honest, and with one gap that a check against the package registry would have caught. That is evidence that the approach extends past a library port, and also of where it needs new checks. One engine in two days is not evidence for other kinds of work in general.
9. What went wrong
- oneocr-csharp has no release after four days. On the sealed test set it trails the two leaders in every category on character error, and an earlier ranking didn’t hold up. A second approach was started and dropped within a day, and an agent-invented data rule had to be overridden.
- The onehtml-csharp interview went wrong at the start. A manager shortened the planner’s questions. Kurtis stopped four managers before one ran the interview the way he asked.
- onegame 1.0 wasn’t usable from NuGet until 1.1.0.
- oneimage-csharp shipped a decoder bug from 1.0 to 1.10.0. Some valid PNG files failed to decode, and the same decoder served TIFF, PSD, SVGZ and WOFF data. It was fixed in 1.10.1. A blur could overflow the stack on tiny images, fixed in 1.10.2.
- onefont-csharp has no published speed comparison.
- Managers sometimes put their own agents ahead of the owner. They relayed points mid-discussion, and once left him waiting.
10. Recommendations
- Count steering, not messages. The strict count separates the factory taking over supervision from the owner choosing to make decisions.
- Cap parallel builds at what the owner and the shared machines can carry. Kurtis set four.
- Write an owner’s correction into the agents in the same hour. Four of the changes his messages prompted went in within ten minutes.
- Leave the planner’s interview format alone, even when an agent answers for the owner. The one refinement that had to be undone was a shortcut there.
- Check that a 1.0 installs from the registry alone before tagging it.
- Give new kinds of work their own outside checks before 1.0. An engine needs a benchmark against another engine and a published list of losses, as the libraries have.
Limits of this report
- Owner messages are found by the first report’s method and coded by one reader under the rules in section 2. Conversations outside the open-source projects were searched by keyword; messages there about the website and posts are not counted.
- Agent runs and cost come from the platform’s run records, with calls cut at each 1.0. Shared project managers are left out, so the totals are low.
- Parallel activity is counted by clock hour from model calls. A project counts in an hour if any of its agents made one call.
- Library results come from each repository at its v1.0.0 tag and were not re-run. Lines of code include comments and blank lines.
- oneocr-csharp is unfinished. Everything said about it describes the record on 27 October.
- The devlog counts tasks by whole day, through 26 October.
Links
- The first report: Alera builds a library factory: from 112 owner messages to 11
- Case studies: Building onepdf-csharp with a team of AI agents · Building oneimage-csharp with a team of AI agents
- All libraries: recursiveai.org/libraries
- Repositories:
- Devlog: recursiveai.org/devlog