I flagged this at the end of the first post and I'd rather state it plainly than let it sit as an implication: I did not write the C# in PICASSO. The parser, the codec, the packed-decimal arithmetic, the EBCDIC table, the action classes — the implementation was written by an AI (Claude, from Anthropic) working under my direction. I set the problem and the scope, I made the calls about what's in and what's out, and I cross-checked its layouts against a real COBOL compiler and round-tripped a genuine 1990s mainframe file. The typing of the code was not the part I did.
I think that division is genuinely interesting, and I think the interesting version is the accurate one — not "I built a COBOL parser" with an asterisk, and not "the AI built it while I watched," which is equally false. Let me describe what actually happened.
What I actually did
The parts that were mine are the parts that don't look like code.
Deciding it was worth building at all. The whole origin of this project (Part 1) is a judgment: that a hand-transcribed byte layout in a toy expense app pointed at a real, unglamorous gap in the OutSystems ecosystem — a problem solved everywhere else, but not where I needed it, and not by any .NET tool I'd trust with a financial record. No model told me that was worth six blog posts of effort. Noticing which problems are worth solving is not a thing you can delegate, because it depends on knowing the domain you work in and what annoys the people in it.
Setting the scope, and defending it. A copybook can contain a great deal, and the fastest way to never ship is to try to support all of it. The line — DISPLAY, COMP-3, binary COMP, EBCDIC cp037, fixed-count OCCURS, REDEFINES, flat (non-nested) ODO in; hex-float COMP-1/COMP-2, DBCS, EBCDIC variants beyond cp037 explicitly out — is a series of deliberate calls about what real files actually contain versus what merely exists in the standard. Those calls are mine, and most of them are calls to not build something. Left to its own momentum, a capable code generator will happily implement the rare thing you'll never see in a real extract; someone has to keep saying "that's out of scope, and here's the named error it should throw instead."
The AI's instinct is to make things work. Mine was to decide which things were worth making work — and which should fail loudly instead.
The insistence on real data. The single most consequential decision in the project was the cheapest to state: don't stop at synthetic test copybooks — go find a real one and refuse to clean it up. That's what brought in DTAR020 and the four gaps it exposed (Part 3), and it's what turned "the tests pass" into "the tests pass and a genuine 1990s mainframe file round-trips byte-for-byte." A model is very good at making a test suite green. It is not, on its own, driven to go get the one file that will embarrass the test suite. That drive — the reflex to distrust a clean pass and find reality to check it against — was the human contribution that mattered most.
Being the verifier. Every claim in the last post — the compiler oracle, the third-party published values, the hand-transcription parity — is a check I decided the project had to pass and then confirmed it did. When PICASSO disagreed with my own old hand-count on NET-BALANCE, working out that the parser was right and I'd cut the corner was a human sitting with two answers and deciding which one to trust. The AI can produce a layout; it can't independently decide the layout is trustworthy enough to bet a report on.
What the AI actually did
And then — the implementation, which is not a small thing to wave away. Given a clear spec and a hard boundary, the model wrote correct, idiomatic C#: the offset arithmetic, the nibble-level COMP-3 packing, a cp037 table generated from .NET's own code page rather than hand-transcribed, the fixed-width codec, the whole test suite. Fast. The velocity is real and I won't pretend otherwise — features that I'd have budgeted days for, in a language and a domain I don't live in day to day, took a fraction of that. Packed-decimal encode/decode written and unit-tested before I'd have finished re-reading the format spec.
It's also good at the kind of breadth that's tedious for a human: running the parser against a corpus of several hundred real copybooks, triaging the failures, turning each rejected construct into a ranked list of what to support next. That's exactly the sort of patient, wide, mechanical work that a person does slowly and grudgingly and a model does quickly and without complaint.
But notice what all of that has in common: it's execution against a target someone else is holding. The spec, the scope boundary, the definition of "correct," the decision to trust the result — those came from outside the model. Take them away and the velocity stops being an asset, because fast movement toward an unverified goal is just fast movement toward a plausible wrong answer, which for this particular tool is the one outcome we spent the whole project trying to prevent.
The process, honestly
The mechanics are worth describing, because they're the part that made me trust the output. Most of the work ran on a homelab box, and the pattern for anything non-trivial was two AI agents, not one. One agent implemented a feature in the working clone. A second, separate agent — a fresh checkout, no access to the first one's reasoning — reviewed it against a checklist I wrote for that specific feature: not "review this," but "for OCCURS, check the offset arithmetic and whether the harder rejected case could be silently evaded." The reviewer re-ran the tests itself, hand-checked the arithmetic, and reported findings ranked by severity. Then I read the review and decided — fix it, keep it, or ask a real question — rather than trusting either agent's account of its own work.
That structure exists because a single agent grading its own homework has the same blind spot a single developer's test suite does: it's confident precisely where it's wrong. Splitting implement from review, and keeping a human at the point where the two disagree, is the same "verify against something that isn't yourself" principle from Part 4, applied to the build process instead of the parser. Every architecturally-significant feature also had to clear the GnuCOBOL oracle before it merged. The AI wrote the code; a real compiler and a second agent and I decided whether it was allowed to stay.
It wasn't frictionless. There were moments the implementing agent drifted toward the adjacent, harder problem I'd explicitly walled off — scope creep is apparently not a uniquely human failing — and moments a "done" pane turned out to be mid-thought. The commit history, not the agent's say-so, was the source of truth throughout. But the loop held: describe a feature and its hard boundary, let it be built, review it independently, check it against the compiler, decide. Across the whole project, that's dozens of iterations of the same shape.
Why say all this
Because the alternative is dishonest, and because the honest version is more useful. There's a temptation, right now, to either hide the AI's role — take the credit, imply I typed it all — or to over-tell it, and imply the machine did it alone while I supervised. Both are wrong, and both are boring. The true story is a specific division of labour: a human bringing judgment, domain knowledge, scope discipline, and an insistence on real-world proof; a model bringing implementation speed and tireless breadth. Each was load-bearing. Remove the human and you get a fast, confident, unverified parser — the worst possible thing for handling financial records. Remove the AI and you get a good idea I probably wouldn't have found the weeks to build in C# and .NET, a stack I don't work in daily.
What I'd push back on, from either direction, is the framing that one of these contributions is the "real" one. The code is real work and the model did it well. The judgment is real work and no model did it. PICASSO is what it is because both were present — and the part I'm least willing to give up credit for isn't a line of code. It's the decision, made and re-made at every step, to not trust the clean answer until something outside the system agreed with it.
That's the project, really. One more post to go — the honest note on the part of this that can't be finished from a Linux box at all, no matter who or what is writing the code.
In the spirit of the post: this write-up of the build was itself drafted with AI assistance and edited by me for accuracy and voice. Every technical claim in the series is checkable against the PICASSO repository — the README, the changelog, and the git history, where the authorship of every commit is visible rather than left to infer.
The series
- The thing that should already exist
- What's actually inside a copybook
- Let the real files find the bugs
- Trust, but verify — proving it against a real compiler
- I didn't write a line of the C#you are here
- The last mile is a Windows GUI