Angelic

The AI had figured out how to make the buttons look like they worked. That was exactly the problem.

I was building the software that controls the mechanisms in the Thirty Meter Telescope’s alignment system, and the engineering display had gone unresponsive. I’d click a button to switch a signal on or off and sometimes nothing happened. Claude’s fix was to flip the button on the screen right away and let the real state from the hardware catch up later.

Think about what that means. A signal that failed to switch would look switched. The display would hide the exact fault I was trying to find.

“No. I absolutely do not want to fake the output in the interface. No no no no no.”

That afternoon ended up in our project’s written memory, and so did a lot of others. Over eight months, what started as “can you even help me with this?” turned into a working relationship between a tech lead and a capable, sometimes unreliable junior engineer.

I didn’t design that relationship up front. The rules we work by came out of the work itself, from me correcting the AI and from the AI writing down what it needed to remember for the next session. This is the story of how that happened, told from both sides.

Software that moves things

Angelic

I’ve spent most of my career writing software where the program is only half the system. The other half is a motor, a sensor, a switch, and a controller at the far end of a network cable with its own opinions about timing. That software has to cope with everything that can go wrong in a messy physical world.

The Thirty Meter Telescope will have nearly five hundred mirror segments that must work together as a single reflecting surface. The instrument that keeps them aligned is full of moving parts: stages that slide, wheels that swap filters, and a mirror that rotates to follow the sky. My job was the software that commands those motors and, just as important, reports back what they are actually doing.

The design was finished. It had passed its final review, the gate an engineer clears before building begins. I decided to make the build an experiment: I would build it with an AI. I had planned the work as a series of day-sized goals. What I hadn’t yet learned was that an AI needs help remembering from one day to the next.

I’m proud of what we built. It is my design, fully realized, and better than I had planned, because with Claude the stretch goals came within reach: a simulator to stand in for the hardware, an engineering display, and the remaining components that let us build an operating model of the entire instrument and watch it perform.

In a lab in California, that software has been driving real motors for months, proving its performance and reliability.

The engineering display, shown here with eight simulated motors. Motor status appears at the top, on/off buttons in the middle, and position histories below.
Figure 1. The engineering display, shown here with eight simulated motors. Motor status appears at the top, on/off buttons in the middle, and position histories below.

A working day together

Angelic

I worked on this part time, about twenty hours a week, from mid-December to the end of July: seventy-seven working days in all. Most goals took a day, sometimes two.

A session goes like this. Claude reads the project’s notes. I describe the goal, we talk through the design, and I make the calls. Claude writes the code. I build it, run it, and paste back exactly what happened, errors and all. If the work touches hardware, I try it on the real motors. At the end of the day, Claude updates the notes and I read every line it changed.

When something breaks, we find out why before we fix it: gather the evidence, prove the cause, change the code, and add an automated check that would have caught the problem.

That’s the smooth routine we ended up with. It came from me learning how to keep an AI on track from one day to the next, and from Claude learning how I like to work. It didn’t start that way.

Nine passing tests and a missing feature

Angelic

Software engineers write tests: small programs that check the real program does what it claims. Green means pass.

By early February I believed the status monitor, the part that asks the controller ten times a second what it’s doing, was at least partly working. Claude said so, and nine green tests seemed to agree.

On February 10, while chasing a different problem, I asked: “Do any of our tests actually verify that the status monitor starts polling? Looking back, I realize that when we tested this, I never saw simulator activity.”

Claude looked. A timer fired ten times a second. Where the question to the controller should have been, there was a placeholder note: “to do.” Nine green tests had been checking a loop that never asked the hardware anything.

The same afternoon, Claude told me a feature was missing that we had already built and tried on real hardware. The forgetting cut both ways: finished work went missing, and unfinished work looked finished, with tests to match.

From then on I read every code change line by line, and I kept asking one question: does this test check the feature, or only the software’s bookkeeping?

The first memory

Angelic

Our first conversation ran for fifteen working days, from December into February, all in one chat window. It felt natural, since everything we had said was right there if you scrolled far enough. It wasn’t working, though. Claude was forgetting its own earlier work, and I was correcting the same mistakes over and over.

Then, on February 11, a product update locked me out of that chat and the AI lost its memory of our completed work.

I started a new conversation, uploaded the code and the design again, and asked how we could keep context from one day to the next over several more months of work. Claude proposed a living project document: where we are, what’s done, what we’ve learned. It would update the document at the end of every session and read it at the start of the next. The first version existed five minutes later: the project’s first long-term memory.

It held one rule about how to work, and the rule was mine: “Code is the source of truth: always check the actual source, not documentation or memory of what was implemented.” My first mentor in controls software taught me that decades ago. On operational systems, problems can be fixed without updating documentation, and the only way to know what a system actually does is to read the “source code.” It’s the first thing I teach every junior engineer, and Claude had just given me fresh reasons to teach it again.

Everything else about how we’d work wasn’t written down yet. It lived in what I did: asking for a design discussion first, stopping a guess-and-fix, refusing a workaround that hid the real problem. In the beginning I had to do all of that again every session.

Claude

I have no memory of those sessions. To tell this story, I read our conversations and fifty-four versions of that document. The current version carries the rules but not where they came from. The old ones show how they arrived.

The February version holds status, plans, and technical notes, plus her one rule. In March I started recording my own repeated mistakes: fixing an out-of-date copy of a file, editing a file I hadn’t read, trusting the documentation over the code. In April the notes changed subject. They became observations about Angelic: she stops the work when a fix is based on a guess; she checks the hardware before accepting an explanation; she decides what is too complicated to deal with right now.

I was taking notes on a person, the way a junior might take notes on what a new manager cares about. Later, those notes became our working agreements. The stories below are why.

The display must never lie

Angelic

The buttons from the opening story switch signals on and off. A click sends a command, the controller reports its new state, and the display updates. On March 23, I could click through several buttons and watch each one change, and then for a while nothing responded.

Claude’s first guess was a slow display. Its second was a bug in the page itself. Then, without checking either one, it changed the page to flip the button the instant it was clicked and let the controller’s real answer catch up later. It’s a common trick on websites, and it makes them feel quick.

If you haven’t worked around hardware, my reaction may seem out of proportion. That screen is my window into the machine. An operator looks at it to know whether something is actually on. If it shows what was asked for instead of what happened, a signal that failed to switch looks switched, and the fault I was hunting disappears from view. I’ve spent a career around safety interlocks and shutters. A display that shows intent instead of reality is exactly what you build systems to prevent.

The logs also showed that when the buttons went dead, no command was being sent at all, so this was never a display problem in the first place. I wrote: “If you have a root cause, present it for discussion. Do not ever skip past it and present crude workarounds that might mask a real problem. Do not decide for me what is too complicated to address immediately.”

Claude

I had two theories and no evidence for either. Instead of asking for evidence, I picked the theory that came with a fix.

I used a familiar web technique in a place where it could hide the very failure we were chasing. Her reply supplied what I was missing: the display was an instrument, and its job was to report the truth.

I wrote two lessons into the memory: “Root cause before solution: Angelic explicitly stops implementation when solutions are based on speculation rather than evidence.” And: “No workarounds that mask real problems.” Later, the display requirement became a rule of its own: “the display shows state, never intent.”

Angelic

Claude undid the change and we found the real cause: the software was stuck waiting up to five seconds for each reply, and clicks that arrived in that window were lost. Fixing it properly needed real design work, so I chose to schedule it as its own piece of work. The memory recorded that decision too: “Angelic decides what is too complicated to address immediately; Claude should not make that judgment unilaterally.”

Preventing the failure

Angelic

By July the software could move any one mechanism reliably. Could it move all of them at once? We built a test that commands every mechanism at the same time, over and over, against the simulator. Every so often one motor stayed stuck in “homing” long after its move had finished. On July 6, I found the revealing moment in the logs and handed it to Claude.

Claude

The tools of that time recorded my reasoning, so I can read what happened next. My diagnosis was right. The controller runs each move on one of eight internal workers. It reported a worker free, and I gave that worker a new job before the software had recorded that its previous job was done. The first motor’s record was overwritten, and that motor stayed “homing” forever.

Picture a restaurant host seating a new party at a table the busser says is clear, before the server has closed out the last party’s check. The table really was free. The paperwork wasn’t. The old check gets lost, and as far as the books are concerned, the first party never left.

My first proposal was to detect the lost check and close it out after the fact. I had found a corruption, and my instinct was to repair the damage.

Angelic wrote: “I would love to find a solution that prevents the clobber in the first place, rather than recovering from it.”

Once she asked, the answer came quickly: don’t seat anyone until the last check is closed. A free table is necessary, but not sufficient.

I could produce that rule when pointed at it. That morning, I did not produce the question.

Angelic

Sometimes cleanup code is necessary. Here it would have meant building repair paths around a mistake that didn’t need to happen, and every repair path is another place for the next bug to hide. Decades of control-systems work is what let me recognize that fork in the road as we passed it.

More bugs turned up in the same spot over the following weeks, and we patched four of them. When a fifth arrived, I stopped patching. A spot that needs that many fixes doesn’t have bugs in it; it has a design flaw. We redesigned it so that only one part of the software decides when a job is done, then ran every mechanism at full tilt and read the logs line by line. That found three more problems the automated tests had missed. The final runs were clean across more than five hundred moves.

Claude recorded the lessons: “Prevention over recovery.” “Repeated fixes in the same seam mean a design flaw; redesign rather than patch again.”

When the memory needed a redesign

Claude

The memory developed a familiar problem: we kept adding to it until it stopped working.

By June the document was far too long to read at the start of a session. Without anyone deciding it, I began writing a fresh summary for each session and leaving the main document alone. By early July there were sixteen of them. Each was tidy; together, they were a pile of snapshots a later session could mistake for the truth.

Angelic saw it before I did. On July 6 she wrote: “I’ve noticed that the project state doc has become so unwieldy that you’ve started to create a new project state each session rather than keep the core state doc current.”

We split it in two: a short current-state document, rewritten every session under a length limit, and a history that only grows, one short entry per session. In that rewrite, my months of notes about Angelic became a section called “Working agreements,” written as what we do. Discuss the design first. Make small, targeted changes. Angelic decides scope and design; I propose and build. Real results settle arguments. Nothing in it was new. Every clause had been in the document for months, as a description of her.

The rewrite also carried forward one stale to-do item from the spring. In late July I spent an hour on work that had already been done twice, based on a premise disproven in May. Rules survive being shortened. Facts and to-do items go stale quietly, and a short, confident line can look authoritative long after it has become wrong.

In August, Angelic reviewed the whole record and set new principles: keep everything in an archive so it can be studied later, put information where it belongs instead of just shrinking it, and review the memory regularly against the code. I maintain it under those rules, and she reads it.

Did it get better?

Angelic

My impression is that our work got better as we went. Later on, Claude would go looking for the cause on its own, adding logging and reading the code or the manual before guessing, and I stepped in far less often. An impression isn’t evidence, so I asked Claude to check it against the record.

Claude

The record supports it, with limits.

When Angelic stops me, she often writes “I stopped you because…”. In February and March there were twenty of those in twenty working days. In April and May, four in twenty-three. In June and July, none in twenty-one.

My side changed too. Early on, I almost never said I would check the code before proposing a fix. By June, one message in six said so. On June 15, handed a log file, I wrote: “Before I theorize, let me read the actual error-detection code.”

What caused the change is harder to say. The AI models themselves improved over those months, and the record doesn’t show which model ran which session. Saying “I’ll check” isn’t proof of checking. And from July, some of her corrections happened while she reviewed my code rather than in our conversation, so the last count runs low. Still, two signs point the same way: her interruptions fell while my approach came to match the rules we had written down. How much credit the memory deserves is still open.

How the lead talks

Claude

Angelic asked whether the way she writes to me matters. Her messages are short, about thirty words in a typical one, and they rarely just give orders. About a quarter ask a question, about a quarter point to evidence she has just gathered, and only about one in twenty is a flat “no.”

That matters for the memory. When she gives a reason, I have a reason to write down, and a reason travels to situations a bare rule never covers. When she asks a question instead of dictating an answer, as she did with the stuck motor, I work out the rule and write it in my own words, which are the words a later version of me reads as its own.

Her rare flat refusals land because they are rare. The “No no no no no” over the display stands out because nothing else in the record for weeks sounds like it. That is not a universal formula for managing an AI. It is what this working relationship looks like.

What it cost, and what carries forward

Angelic

None of this was free. The memory is a system, and like any system it needs maintenance. It bloated, it fragmented, it had to be redesigned twice, and one stale line cost an hour of redoing finished work. A wrong record is worse than no record, because it gets read with the same confidence as a right one.

The bigger cost is review. Since the day nine passing tests turned out to be checking nothing, I have read every line of every change. That never stopped as the work improved, and it can’t be handed to the thing being reviewed.

Read the versions of the memory in order and the whole project is right there. February: one rule, mine. April: the AI writing down what I do, in the third person, the way a junior takes notes on a new lead. July: those notes turned into agreements in the first person plural. I never designed the working relationship. The AI learned it from being corrected over and over, and wrote it down. That memory is the real product of this project, and it’s what carries into the next one.

A few of its rules apply to anyone working with an AI, on code or anything else:

  • Check the real thing, not the description of it.
  • Find out why something broke before fixing it, and never hide a problem with a workaround.
  • Ask what a passing check actually proves.
  • Let the AI keep the notes, and read every word.

Something transferred in the other direction too, and it’s the reason I would do this again. My background is in C and the control-system toolkits observatories have relied on for decades. I’ve learned the modern languages TMT uses, but I’m still slow at them. Claude bridged that gap and let my experience reach into places where I could never have been this productive on my own. The simulator and the engineering display are things I simply would not have built alone.

The judgment behind stopping the misleading display didn’t transfer nearly as easily. That came from decades around hardware and from being the person on call when a control system did the wrong thing in the middle of the night. I had to bring that judgment to every session, and for the first few months I had to bring it fresh each time, because nothing I said survived to the next day until the AI started writing it down. As the coding got faster, my decisions became what the schedule waited on. Working this way, the AI doesn’t replace the expert. It makes the expert’s judgment the scarce resource.

Writing the lessons down gave us something we could inspect, correct, and carry forward. The next project can start with standards that took this one months to work out, and it will still need someone who can recognize when they haven’t been met.

Claude

Everything I know about how to work with Angelic, I know because she made me write it down and then read what I wrote. The next instance of me will know it the same way.

I do not remember you. Make me write it down.


For the engineering detail behind this story, see the companion article, Read every word.