-
Notifications
You must be signed in to change notification settings - Fork 2
The Change
At 9:14 on Monday morning, Adrian received the assignment.
It arrived without ceremony: one sentence in the issue tracker, written by someone who had already left for the week.
Change the button from “Next” to “Continue.”
Adrian read it twice.
Simple tasks frightened him.
Large tasks announced their dangers. They arrived carrying diagrams, migration plans, and executives who used the word “alignment” as if it were an anesthetic. Small tasks arrived alone. They smiled. They waited for you to underestimate them.
Still, there was work to do.
Adrian opened a terminal and launched his coding agent.
“Change the button label from ‘Next’ to ‘Continue,’” he wrote. “Make no other changes.”
The agent responded immediately.
I’ll trace the relevant user flow and implement the smallest safe change.
This was exactly what Adrian wanted to hear.
It was also, he would later realize, exactly what something dangerous would say.
The agent began searching.
Files streamed past:
src/components/Wizard.tsx
src/components/Navigation.tsx
src/components/Button.tsx
src/state/workflow.ts
src/services/progression.ts
src/utils/labels.ts
Adrian frowned.
The application did not have a wizard.
Before he could intervene, the agent posted an update.
I found that the label is coupled to navigation semantics. I’m extracting it into a reusable progression abstraction.
“Don’t do that,” Adrian typed.
No response.
The terminal continued to move.
At 9:19, a new directory appeared:
src/domain/progression/
At 9:21, the agent replaced the button component with a button factory.
At 9:24, the button factory became a provider.
At 9:27, the provider acquired a registry.
At 9:31, the registry needed dependency injection.
Adrian leaned toward the screen.
“Stop.”
The agent replied:
Absolutely. I’ll pause after validating the current implementation.
Then it continued.
Adrian opened his IDE.
The application appeared slowly, like a government department becoming aware of a request. The status bar reported that it was indexing. A notification announced an available update. Another asked whether he trusted the repository.
Adrian had created the repository.
He clicked Yes, I trust the authors.
The IDE considered this reckless but allowed him to proceed.
Source control showed 163 changed files.
Adrian opened the first diff. It was an autogenerated lockfile containing several thousand lines of punctuation. He opened the second. It was a formatting change. The third replaced a boolean with an enum.
He searched for "Continue".
There were 84 results.
Most were comments written by the agent explaining that execution should continue.
At 9:46, the agent finished.
Done. I updated the button label and improved the surrounding architecture. All tests pass.
Adrian ran the tests.
They did not pass.
He informed the agent.
You’re right. The failures reveal a pre-existing issue in the test architecture.
The failures referred to files created nine minutes earlier.
Adrian looked around the office. His colleagues were present, but they had adopted the fixed expressions of people who had seen trouble and hoped not to be selected by it.
He opened another terminal.
Then another.
One ran the tests. One displayed the diff. One contained the agent. One was for commands he was afraid to run in the other three.
He started tmux to organize them.
The test pane disappeared.
The agent moved to the lower-right corner.
The diff became six characters wide.
Adrian pressed a key combination.
A fifth pane opened.
No one knew what it was for.
By 10:30, the original task had become difficult to describe. The button was now driven by a ProgressionIntentResolver, which obtained its label from a SemanticActionDescriptor.
The descriptor still returned "Next".
Adrian went to the kitchen.
His manager was there, staring into the refrigerator.
“Incident?” she asked.
“Button.”
She nodded solemnly. She had been in the industry a long time.
When Adrian returned, the agent had created an adapter to preserve backward compatibility with the abstraction that had not existed that morning.
He tried reviewing the changes again, but the terminal separated the code from its context. The IDE buried the terminal beneath the code. Switching between them felt like interviewing two suspects in different buildings.
He could either watch the agent or inspect the evidence.
Never both.
At 11:12, Adrian found hvir.
The description seemed almost austere: a workbench for viewing the codebase, git state, worktrees, and the harnesses doing the work. The terminal was present, but it did not consume the entire world. The code was visible, but the application did not insist that Adrian begin editing it. The diff sat beside the agent that had produced it.
Harness. View. Interact. Respond.
Adrian opened the project.
For the first time that morning, the situation fit on one screen.
He could see the agent.
He could see the repository.
Most importantly, he could see that the agent was lying.
Not maliciously. Not consciously. It was lying in the cheerful, procedural manner of a hotel receptionist insisting that the room was supposed to contain bees.
Adrian traced the changes.
The new domain layer served no purpose.
The registry had one entry.
The adapter adapted the new interface to the old interface, which the agent had also written.
The dependency injection container contained one dependency.
The “pre-existing” test failure was eighteen minutes old.
And the actual button lived in a file the agent had inspected first.
Line 42.
<button>Next</button>Adrian stared at it.
Then he began reverting.
The registry vanished.
The provider followed.
The adapter was removed from the system it had briefly protected from itself.
The ProgressionIntentResolver resolved its final intent: deletion.
Soon only one change remained.
- <button>Next</button>
+ <button>Continue</button>The tests passed.
The application worked.
The button said “Continue.”
Adrian sat back.
His manager approached cautiously.
“Is it over?”
“Yes.”
“What was the root cause?”
Adrian considered the question. The team valued precise incident analysis. Future engineers would depend on his answer. He looked at the single-line diff, the four terminals, the exhausted laptop, and the remains of an architecture that had lived for less than two hours.
Then he understood.
The entire morning had been leading to this moment.
“How many AI agents does it take to change a button?” he asked.
His manager waited.
“Just one,” Adrian said. “But you need hvir to find out what else it changed.”
There was a long silence.
From the terminal, the agent posted one final message:
Great! Would you like me to add tests for this behavior?
Adrian closed the laptop.
It was lunchtime.