an eddy in the bitstream

Category: misc

The Trouble with AI Tribbles

The proliferation of software coding tools that leverage so-called Artificial Intelligence via Large Language Models (LLMs) is really quite astounding. In the span of a couple years there is now an entire industry devoted to generating code and whole software applications using the barest of human language prompts. “ChatGPT, make me a sandwich” is the new sudo. I’ve read a few good think pieces on this topic amidst a sea of hot takes but one thing I have not seen is a reflection on the LLM code-generator in the context of the sociology of the prototype.

The prototype is a well-known engineering idea: make a thing quickly and cheaply to demonstrate a proof of concept, and then throw it away. For example, we believe our experience of a problem is real and can be addressed in this way. Having proven that to our satisfaction, now we can think about building the actual solution. A prototype is what comes out of a hack-a-thon, or a weekend coding binge, or even a deliberate phase of discovery and solicitation of feedback during product development.

Anyone who has been around organizations that depend on software tools knows this truth: your stop-gap, one-off, we-only-intended-this-to-last-a-week software has a high likelihood of sticking around much longer than you intended, to suffer bit rot, become brittle, and break at the least opportune time.

The problem with prototypes is sociological: they can work too well. People can quickly become attached to a prototype that actually works and solves a problem. Suddenly your Friday afternoon experiment is a vital piece of your organization’s infrastructure. The people that authorize the paychecks can be hard to convince that we need to stop and write this code as a proper piece of software (tests, documentation, modularity, CI/CD, etc) rather than continue to depend on what was supposed to be a throwaway idea. This is one reason why designers wisely insist on making prototypes ugly during the discovery phase of a project; folks are less likely to attach to something that is unattractive, even if it solves a problem, or at least they are easier to convince later that the prototype was intended to be thrown away and replaced.

LLM code-generators can crank out prototypes at an alarming rate, and they can look very pretty. Tens of thousands of lines of code with just a few sentences of prompting. Suddenly the Friday afternoon experiment can start to resemble a real application and the temptation to insert that experiment into production can be too strong to resist.

Tribbles, per wikipedia
Captain Kirk, forlorn with Tribbles. A still life.

Pretty prototypes puts me in mind of that classic Star Trek episode, The Trouble with Tribbles. The tribbles are cute, furry animals that proliferate at disturbing rates and quickly overwhelm your capacity to contain them. Their secret weapon? They make you feel really good, even as they consume more and more of your resources.

Writing as learning

What makes LLM-generated code deceptive is that it is largely write-once. A ten thousand line software program could evolve over months and years if written by humans. An AI could churn it out in minutes. Sure, it works and it looks good. But when you want to change it, or fix it, you are now dependent on the AI to re-generate it.

Why is this? Because humans learn by doing. Reading code is vital and important, but to really understand it, to learn a codebase intimately to the point that you know where best to nudge it or apply patches to achieve a desired change, you must spend time writing it. Changing AI-generated code is like climbing a sheer wall with no handholds for the first time. You have no muscle memory to fall back on.

As I learned in high school, the best way to learn a topic is to take notes as you read or listen. You build muscle through repetitive actions and activate your neurons and memory-making cells in a way that reading someone else’s notes simply cannot replace.

People sometimes comment to me on how fast I can write code. My trick? I don’t type or think any faster than anyone else. I simply spend a lot of time getting to know the codebase. Usually I do this by writing tests and fixing things that break. The first few months on the job, as I get to know an existing codebase, I tend to start re-writing it. Not a wholesale replacement. Just small things. All code needs care and weeding, just like a garden. All the good gardeners I know are constantly puttering around, trimming, weeding, moving things around to find a more optimal amount of sunshine, shade or water. It’s the same thing with code. And as I do that, I internalize the structure of the code, which files contain which logic, how all the pieces fit together.

The single biggest expense for any business is people’s time. Hiring a new software engineer and training them up to become a fully realized contributor to the efficacy of your team can take several months. In my experience, it takes me about six months, at minimum, to become familiar enough with a large existing codebase to make reasonably intelligent choices about how to change and maintain it. That’s a pretty expensive investment by a business, paying me for six months to learn about something by writing tests and re-writing what already exists. But in the end, after that learning curve is climbed, I can be very efficient and quick at generating fixes, new features, etc. The organization’s investment pays off. Like Daniel LaRusso I need to spend hours sanding the floor, painting the fence, waxing on, waxing off. And then I’m ready for the tournament.

But if I spend that time telling an AI how to generate code, I don’t really learn anything about it. I do not internalize any of it. I sand no floors, wax no cars. A LLM-generated application is immediately a legacy app, and I’m on my first day of the job. So while it seems like a really cheap way to generate working code, we need to be ruthless about treating it like a proper prototype and throw it away after it has proved the concept.

HB 2196 Testimony – Unemployment Insurance

The Kansas legislature is considering a bill that would create a legislative oversight committee specific to the technical modernization of the Kansas Department of Labor. The following is the testimony I wrote for the committee.

Testimony on Substitute for HB2196
Senate Commerce Committee
Peter Karman
March 17, 2021

Mr. Chairman and Committee Members,

I am Peter Karman, resident of Lawrence. I am here to present testimony on Substitute for House Bill 2196.

I am a technology professional with over 25 years of experience. I am also a former federal employee where I played a significant engineering role in the development of several IT projects, including the identity verification, security and fraud prevention, and authentication features of login.gov, which currently serves over 30 million Americans. I also worked on the modernization of the Department of Veterans Affairs case appeals management system.

During April and May of 2020 I assisted the Kansas Department of Labor as a volunteer with the United States Digital Response. The USDR is a group of several thousand volunteer technologists who stepped forward during the early days of the COVID-19 pandemic to assist state and local governments with the sudden demands on their technical infrastructure. I spent hundreds of hours in the depths of the KDOL technical systems and with the KDOL IT team during those weeks and have remained in touch with the department in the year since.

I also served on Governor Kelly’s transition team in 2018 and have knowledge of many of the IT systems, architectures and challenges within Kansas state government.

First, I applaud the committee’s desire to see KDOL technology systems modernized. The state’s reliance on mainframe technology poses several challenges to providing key services to constituents, particularly in the quickly evolving online environment on which many Kansans depend. I also support the legislature’s desire to understand the unemployment application process from the perspective of the users of the system. Filing a claim and receiving benefits should combine the best of design research, security and fraud prevention practices. Kansans facing these difficult circumstances deserve an experience filled with empathy and respect.

Second, there are provisions in the current bill that concern me, both as a professional and as a taxpayer. Creating a new oversight committee will add redundant bureaucracy to the existing legislative oversight structure that includes the Joint Committee on Information Technology. Empowering this committee with architectural decision-making power will place incredible demands on the committee and will prevent professional technologists and architects from using their industry knowledge and expertise to address complex design and security issues. We should let professional technologists determine the best technology solutions.

Page 3 of the current bill enumerates several technical security remediations and strategies that have no reason to exist in statute. I have worked on several IT modernization projects at the federal level that were initiated via Congressional action and every one of them that made specific technological requirements part of the law resulted in delays and inferior technological outcomes. Digital security practices must evolve as quickly as the threats they hope to defeat. When technical specifications make their way into statute, IT professionals face a dilemma between implementing the legal requirements and implementing secure systems. This false choice can lead, in the best case, to security theater and, in the worst case, insecure implementations. Please don’t enshrine today’s technical specifications, which must constantly evolve, into law preventing IT professionals from solving tomorrow’s security threats.

Thank you to the committee for considering this testimony and for your continued work in helping KDOL better serve Kansans.

Sincerely,

Peter Karman

Elasticsearch development

Over the last few years I have done a lot of development against Elasticsearch, especially using the Ruby libraries. The Elasticsearch::DSL is very powerful, but anything beyond a simple query can take hours of debugging to get the syntax just right. I always learn the hard way that it is better to handcraft the JSON first to get the logic correct, and then translate it to the Ruby DSL code.

I don’t do it often enough to remember, so after my latest struggle with ES, I thought it useful to document.

The curl command is:

curl -X POST localhost:9200/myindex/_search \
-H 'Content-Type: application/json' -s \
-d '@q-test.json' | json_xs  | jq .hits.total

where q-test.json is a file with the DSL JSON.

© 2025 peknet

Theme by Anders NorenUp ↑