Episode 3

Foundation Building Begins

"The first test is an accusation"
39 min read

Ethan Carter doesn't start with a rewrite. He starts with a test harness: plain-English scenarios that copy files into the INCOMING folder, kick off the COBOL batch on the test server, wait for the output, and check the numbers. A tool called Cucumber. Ruby underneath. No VB6 client needed. No Micro Focus license. Just input, output, and an honest answer. Nathan Cole watches someone prove that the nightly run can be questioned in daylight. He hasn't felt hope in years. Linda Pritchard watches the same thing and feels the ground shift. The moat is draining, one scenario at a time.

Previously: "When VB6 Was the Future" — Thomas Whitaker stopped learning when the platform changed. The company froze in 1998, and when Thomas died, his son inherited the frozen future as if it were a gift.

Monday, 08:37 — The Contractor

Gray October morning in a small Ohio office lobby. Ethan Carter: early 40s, dark jeans, worn leather boots, plain black t-shirt under a charcoal zip hoodie, messenger bag with laptop sleeve sticking out, short unshaven stubble, calm eyes that have seen worse systems. Nathan Cole: late 30s/early 40s, rumpled button-down with sleeves rolled up, coffee stain near the placket, tired eyes, posture tense like he expects alarms. Derek Lawson: navy suit, crisp white shirt, expensive belt, polished watch, holding a visitor badge and a clipboard. Behind them: framed trade show photos, a reception desk with a faded artificial plant, fluorescent lighting.
"Ethan Carter arrived ten minutes early because people who've lived through real outages don't trust calendars."

Ethan Carter arrived ten minutes early because people who’ve lived through real outages don’t trust calendars.

Outside, rain dragged itself down the glass doors in slow, patient lines. His boots left wet crescents on the lobby tile. The air was too warm for October, pumped out by a thermostat that had never been calibrated and never would be.

He stood still and listened.

Not to the lobby music, because there wasn’t any. To the building’s rhythm. The muffled ring of phones deeper inside. The cough of a printer. The slightly-too-fast footsteps of someone hurrying to solve a problem that should’ve been solved years ago.

Ethan had a private checklist that lived behind his eyes.

What breaks at night.

What breaks on Friday.

What breaks when the one person who knows the incantation is sick.

The lobby smelled like lemon cleaner and old carpet. A framed photo on the wall showed a younger Graham Whitaker shaking hands at a trade show booth, smiling like reliability was a personality trait.

Derek Lawson walked out first.

He looked Ethan up and down and smiled with the correct amount of welcome.

“Ethan. Great.” Derek’s smile widened a notch. “Preston spoke highly of you. Said you’re the guy who’s… good at coding.”

He said it like the highest form of praise was being useful without being complicated.

Nathan watched Derek say Preston’s name like it was a security badge. A blessing. A shield.

Nathan’s stomach tightened.

The last “guy who’s good at coding” had lasted three weeks.

“I sent the retainer structure and scope doc,” Ethan said. No ego. Just a boundary.

Derek nodded without absorbing it. “Sure, sure. We’ll get you started. Just work with Nathan. Keep the payroll running.”

Nathan Cole stepped into view behind Derek, coffee in hand, shoulders slightly hunched like gravity had negotiated special privileges.

His coffee was bitter and lukewarm. He’d already had one at home, standing in the kitchen while his younger kid asked if he was really making it to dinner tonight. He’d said yes too fast. He’d already promised himself he wouldn’t have a second. He’d already failed.

Nathan didn’t shake Ethan’s hand immediately. He studied him the way you study a new medication.

Hope had side effects.

“Morning,” Nathan said.

“Morning,” Ethan replied.

Derek handed Ethan a visitor badge. “We need you to… you know… help with some coding. Stuff keeps breaking. Nathan’s been carrying it.”

Nathan’s eyes flicked to Derek, then away.

Carrying it.

Like this place was a box Nathan could pick up and put down when he was done.

Ethan looked past them, down the hallway.

“Before I touch anything,” Ethan said, “how do changes move around here? Where do you build, where do you test, and what box runs the overnight batches for real?”

Derek blinked. “We have the live system. The real one. The one that runs payroll.”

Nathan exhaled through his nose. A sound halfway between a laugh and a surrender.

Don’t ask that out loud, Nathan thought. Don’t name the lie.

“We have dev machines,” Nathan said. “We have a ‘test’ server that’s supposed to look like the live system, except it doesn’t. And a shared SQL instance someone upgraded in 2019 and nobody remembers how.”

Ethan nodded slowly.

He didn’t look impressed. He looked relieved.

“Okay,” he said. “So we start by making reality repeatable.”

Nathan’s throat tightened.

Repeatable meant you could hand the problem to someone else. It meant 02:18 didn’t belong to him anymore.

That sentence hit him harder than it should’ve.

Not because it was profound.

Because it was sane.

Monday, 11:14 — The Harness

Open-plan office with low cubicle walls and aging monitors. Ethan Carter and Caleb Turner sit side by side at a desk. Ethan: hoodie sleeves pushed up, forearms on the desk, focused on screen. Caleb Turner: late 20s, graphic tee under a flannel shirt, jeans, sneakers, trying to look confident, eyes darting between Ethan and the screen. On the monitor: a text editor with a .feature file open showing Gherkin syntax (Given/When/Then steps), and below it a black terminal window with green and red text. A Windows Explorer window shows two shared folders labeled "INCOMING" and "OUTGOING." Nathan Cole stands behind them holding a coffee cup, watching. Olivia Parker: early 30s, ponytail, cardigan over a blouse, notebook open, leaning against a file cabinet. Ryan Mitchell: early 30s, beard, casual button-down, arms crossed, leaning forward. Linda Pritchard in the background: dark cardigan, binder hugged to her chest, lips pressed flat. Fluorescent lights.
"Ethan didn't do the first-day performance."

Ethan didn’t do the first-day performance.

No jokes. No careful speech about “culture.” No tour of the floor like he was here to admire the wallpaper.

He moved like someone who’d learned, the hard way, that talk is how broken systems stay broken.

He put his bag on the floor, pulled a chair in close, rolled his sleeves up, and aimed for pain.

He also didn’t start with the VB6 screens.

Not because he didn’t care. Because the development tools were dead.

The VB6 runtime still shipped with every copy of Windows. Microsoft had kept that promise for twenty-six years: existing VB6 applications would keep running. The payroll client still launched on customer desktops. It still talked to the database. It still generated flat files and sent them via FTP. The runtime was immortal.

The IDE was a ghost.

Microsoft had stopped supporting the Visual Basic 6.0 development environment in April 2008. You couldn’t buy it. You couldn’t download it. If you still had the original install media from 1998, you could try to install it on Windows 11, and it might work, sort of, as a 32-bit process running under emulation, flagged as “unknown publisher” by the operating system, breaking a little more with each Windows update. A few people around the world still did this, the way a few people still drove museum cars on public roads. Technically possible. Nobody’s idea of reliable.

But the IDE was only half the problem. The VB6 ecosystem had been a living thing: third-party component vendors selling grids, charts, date pickers, report generators. Thick catalogs arriving in the mail. ActiveX controls with .OCX extensions and licensing files and installer routines. Microsoft’s own support page still said “Customers are encouraged to contact the original control vendor.” The original control vendors were bankrupt, acquired, or pivoted to .NET fifteen years ago. The components the payroll client depended on existed only as binary artifacts on machines that had never been reformatted. If those machines died, the controls died with them. You couldn’t recompile the client without the controls. You couldn’t get the controls without the vendors. The vendors were gone.

COBOL was worse.

Micro Focus lived on Nathan’s machine like a curse you didn’t lift because the patient would die. One fragile setup. One license. One set of keys. The other developers had never touched it. Caleb Turner was twenty-eight years old. He had never seen a COBOL compiler in his life. Olivia Parker and Ryan Mitchell were in their early thirties. COBOL was something their professors had mentioned in a history-of-computing lecture they’d half-slept through.

Ethan could read COBOL the way you read a language you learned once and never spoke. Slow. Careful. Enough to understand what a paragraph meant. Not enough to change a comma without risking the whole sentence.

Writing it? Compiling it? Touching the batch binaries?

That was Nathan. Only Nathan.

So Ethan started with the only part of the system that didn’t need a license, a dead installer, or a blessing from the past.

Files.

The flat text that arrived by FTP every evening from customer sites. The flat text that left the building as paychecks and tax reports the next morning. Input and output. Evidence you could hold in your hands.

Between those two files sat fifty years of COBOL logic that nobody alive could fully explain. But the files didn’t care about explanations. Files were facts. If you could feed facts in and check facts out, you didn’t need to understand the machine. You just needed to know whether it was lying.

Caleb Turner had been assigned as Ethan’s “shadow,” which meant Derek had decided Caleb was expendable for a few hours.

Caleb tried to look like he’d been chosen for his potential.

He knew the truth. He’d been chosen because he didn’t have enough institutional gravity to say no.

His leg bounced under the desk. He kept his hands flat on the keyboard like that would keep them from shaking.

“Show me one thing that hurts,” Ethan said.

Caleb laughed once, sharp. “Pick a day of the week.”

“Pick one.”

Caleb clicked through a folder tree full of dead attempts and half-started projects.

“State tax rounding,” Caleb said. “Sometimes it calculates different for the same employee depending on which client file the entry came from. Detroit’s got a city income tax on top of the state tax, and sometimes the numbers come out wrong. Linda says it’s always been that way. Nathan fixes it by hand at 02:00.”

Ethan stared at the screen.

“What do you do when it happens?” Ethan asked.

Caleb’s ears reddened. “We rerun the batch.”

He heard himself say it and his throat went tight.

Rerun the batch wasn’t a solution. It was a confession. It meant: we don’t know why it fails, so we run it again and hope the answer changes.

Ethan didn’t react. Not visibly. But he recognized the sentence. He’d heard it in a dozen other buildings, in different words, from different mouths. The confession was always the same: we don’t have proof, so we pretend the problem doesn’t exist until it hurts someone.

“Write it down,” Ethan said. “One specific case. Make up names and numbers. Something we can talk about without involving a real person’s paycheck.”

Caleb looked at Nathan.

Nathan stood behind them, coffee in hand, watching. He’d been watching since Ethan sat down. Not intruding. Not leaving. Standing in that careful no-man’s-land where hope and suspicion trade shifts.

Nathan nodded, barely, and recited from memory: “Flat text. Fixed-width columns. Employee ID, name, state code, city, hours, rate, filing status. That’s what the VB6 clients generate. One line per employee.”

The words came out automatic, like a prayer he’d recited so many times it no longer required faith.

Ethan opened a terminal on his laptop. His fingers moved quickly but without urgency. He created a project folder called harness. Inside it, a subfolder called fixtures.

He typed a flat text file. One line. Fixed-width columns, exactly the format Nathan had described:

001  TEST EMPLOYEE       MI  DETROIT     40.00  25.00  S

One fake employee. Forty hours at twenty-five dollars an hour. Detroit, Michigan. Single filing status.

The file looked exactly like something a VB6 client would have generated and sent via FTP. Except no VB6 client had made it. Ethan had, on a laptop that had never touched VB6 and never would.

He saved it as midwest_manufacturing.dat and placed it in the fixtures folder.

Caleb frowned. “What’s that do?”

“Nothing yet,” Ethan said. “That’s the input. Now we write the expectation.”

He created another folder inside the project: features. Inside it, a file called state_tax.feature.

He typed slowly. Deliberately. Letting Caleb and Nathan see every word appear on screen.

Feature: State tax withholding
  Payroll batches calculate federal, state, and local
  withholding based on jurisdiction and filing status.

  Scenario: Employee in Detroit with city tax
    Given a payroll file for client "Midwest Manufacturing"
    And an employee in "Detroit, MI" who worked 40 hours at $25.00
    When the batch processes the incoming file
    Then the gross pay should be $1,000.00
    And the MI state withholding should be $42.50
    And the Detroit city tax should be $18.40

Caleb read it twice.

His frown changed shape. Not confusion anymore. The kind of frown you make when you realize the wall you thought was load-bearing was actually cardboard.

“That’s just sentences,” Caleb said.

“Structured sentences,” Ethan said. “A tool called Cucumber reads this file. Each line maps to a piece of Ruby code that does something concrete.”

“Ruby,” Caleb repeated, like he was tasting a word he’d only seen on job listings.

Ethan nodded. “Ruby runs the automation underneath. Cucumber is the layer on top that speaks English. The point is that anyone in this building can read this file and know exactly what we’re testing. No programming required. Just English.”

Behind them, Nathan’s grip on his coffee cup tightened.

English.

The word echoed in his head. Not because it was surprising. Because it was dangerous.

If the tests were written in a language only developers spoke, nobody else would bother reading them. The SMEs would dismiss them as “programmer stuff” and go back to their binders.

But English.

English meant Linda could read them.

Nathan swallowed.

Caleb leaned closer to the screen. “So where’s the Ruby part? The part that actually does something?”

Ethan pointed at the features folder and created a subfolder inside it: step_definitions. Inside that, a file called payroll_steps.rb.

“This is where the sentences connect to reality,” Ethan said. “Watch.”

He pointed at the first line of the scenario.

“‘Given a payroll file for client Midwest Manufacturing.’ When Cucumber reads that line, it triggers a piece of Ruby code. That code takes the fixture file we just created and copies it into the INCOMING folder on the test server. Same shared folder where the real client data lands every night via FTP.”

Caleb’s mouth opened slightly. “Just… copies it in?”

“The COBOL batch doesn’t care who put the file there,” Ethan said. “It picks up whatever lands in INCOMING and processes it. VB6 client, a Ruby script, a human dragging a file with a mouse. The batch doesn’t know the difference.”

Nathan felt his pulse jump.

He’d known this for years. He’d never heard anyone say it out loud. The VB6 client was dead, but the files it generated were just text. Flat, stupid text. Anything that could write text could replace the VB6 client for the purpose of feeding the batch.

The insight was so obvious it was embarrassing. And nobody had acted on it in all the years since VB6 died.

Ethan moved his finger to the next line.

“‘When the batch processes the incoming file.’ That line triggers the batch itself. Same COBOL executable that runs at 02:18 every night.” He looked at Nathan. “How do you kick it off manually?”

Nathan hesitated.

He could feel the habit trying to take over. The habit of not touching anything. The habit of surviving. The habit of protecting the system by keeping everyone else away from it.

He pulled a sticky note from beneath his keyboard and slid it across the desk. A server name. A network path. A password that looked like someone had typed it in 2004 and never changed it.

“Scheduled task,” Nathan said quietly. “You can trigger it from the command line. schtasks /Run /S and the server name. Task is called PayrollBatch.”

Ethan typed the command into the Ruby step definition.

“The Ruby code triggers that task,” Ethan said. “Then it waits. Polls the OUTGOING folder every few seconds. When a result file appears with a timestamp newer than when we kicked off the batch, it knows the run is done.”

Caleb was very still. His leg had stopped bouncing.

“And the last part?” Caleb asked.

Ethan pointed at the Then lines.

“‘Then the gross pay should be one thousand dollars.’ The Ruby code opens the output file in OUTGOING. Reads the numbers. Fixed-width columns again. Checks whether gross pay, state withholding, and city tax match what we wrote in the scenario. If they match, the step passes. If they don’t, it fails.”

“Fails,” Caleb repeated.

“Fails with a message. Expected this, got that. No ambiguity. No argument. The numbers either match or they don’t.”

Caleb sat back in his chair.

“So it does what a person would do,” he said slowly. “Drop a file in the folder, kick off the batch, wait for the output, check the numbers. Except…”

“Except it writes down what it expected before it looks at the answer,” Ethan said. “And it does it the same way every time. It can’t forget. It can’t round in its head. It can’t decide the result looks close enough.”

Nathan felt something shift in his chest. A loosening. The kind you feel when you’ve been holding your breath for so long you’ve forgotten what breathing feels like.

This wasn’t a simulation. This wasn’t a proof of concept. This was a harness around the live batch. No dead tools required. No Micro Focus license. No VB6 client. Just files in, batch runs, files out, and an honest answer.

“Let’s run it,” Ethan said.

He typed a single command into the terminal:

cucumber features/state_tax.feature

The screen went quiet for a moment. Then text started scrolling.

Feature: State tax withholding

  Scenario: Employee in Detroit with city tax
    Given a payroll file for client "Midwest Manufacturing"
    And an employee in "Detroit, MI" who worked 40 hours at $25.00
    When the batch processes the incoming file

The cursor blinked. Waiting.

A minute passed. Nobody spoke.

The batch was running on the test server. The COBOL executable that Thomas Whitaker had compiled with Micro Focus sometime in the late 1990s was processing a fixture file that hadn’t existed ten minutes ago.

Nathan could hear his own heartbeat in the silence.

Two minutes. Three. Caleb shifted in his chair. The fluorescent light above them ticked faintly, the way fluorescent lights do when you’re waiting for something and the universe wants you to know it’s in no hurry.

Four minutes. Ethan sat still, arms folded, watching the cursor like a man who’d done this before and knew the waiting was the price.

Five minutes.

Then the output continued:

    Then the gross pay should be $1,000.00
    And the MI state withholding should be $42.50
    And the Detroit city tax should be $18.40
      expected: 18.40
           got: 14.40 (FAILED)

1 scenario (1 failed)
6 steps (1 failed, 5 passed)
5m17.482s

FAILED.

The word sat on the screen like an accusation.

Clean. Honest. It didn’t negotiate.

Expected $18.40. Got $14.40. A four-dollar difference that had been hiding inside the nightly batch for God knows how long, visible only when someone manually caught it and called to complain.

Now it was visible at 11:14 on a Monday morning to anyone who could read English.

Silence fell around the desk. The kind of silence that happens when a room realizes something it didn’t know was possible.

Nathan set his coffee cup down because his hand was trembling and he didn’t trust himself to hold it.

He hadn’t seen the system accuse itself. Not once in all his years. He’d seen error logs. He’d seen stack traces. He’d seen Linda shake her head and say “it’s always been that way.” But he’d never seen a plain-English sentence on a screen that said: here is what should happen, here is what actually happened, and the two don’t match.

His brain tried to reject it the way it rejected sleep.

This is dangerous, it whispered.

This is evidence.

Two of Nathan’s developers had drifted closer.

Olivia Parker leaned against a file cabinet with her notebook open, pen hovering above paper without touching it. Her eyes were locked on the terminal output. Her phone, faceup beside the notebook, lit once with a daycare reminder before she turned it over without reading the rest. Ryan Mitchell stood behind Caleb with his arms crossed, but his posture leaned forward anyway, like curiosity had grabbed him by the collar. A blue crayon streak still marked the edge of one cuff where somebody small had hugged him before work.

Olivia spoke first. “That failure. Is it real?”

Ethan tapped the screen lightly. “It’s as real as whatever the COBOL does. The fixture file went in. The batch ran. The output came out. The numbers don’t match what we expected.”

“But the expected numbers,” Olivia pressed. “How do we know those are right? Who says Detroit city tax should be $18.40?”

Ethan looked at her. She was asking the correct question.

“Nobody says it yet,” Ethan said. “That’s the point. Right now we typed in what we think is correct based on what Caleb told me. If we’re wrong about the expectation, we change it. If the batch is wrong, we’ve caught a bug. Either way, we learn something.”

Ryan uncrossed his arms. “So we can stop arguing about whether it’s a rounding error or bad input data.”

“Now we can argue about what the right answer should be,” Ethan said. “Which is at least an argument you can win.”

Caleb was staring at the terminal with an expression Nathan recognized. Not excitement exactly. More like the look on someone’s face when they discover the door they’ve been pushing against was unlocked the whole time.

“Can we run it again?” Caleb asked.

“Right now if you want,” Ethan said.

“And it’ll do the same thing? Same file, same batch, same check?”

“Every time.”

Caleb exhaled. “We’ve never had that.”

Nobody answered because nobody needed to.

Behind them, Linda Pritchard cleared her throat.

The sound landed like a gavel.

Everyone turned.

Linda held her binder against her chest like a shield. The binder was thick and dog-eared, stuffed with printouts that smelled faintly of toner and hand lotion. The physical weight of the rules. The kind of weight you could trust when people changed their minds.

“I’m not sure this is the moment for something this fragile,” she said.

Her voice was calm. Her knuckles were white around the binder.

“This payroll runs every night,” she continued. “If you break it, people don’t get paid Friday.”

Ethan didn’t flinch. He didn’t argue. He pointed at the terminal behind him without looking at it.

“That test didn’t change the batch,” he said. “It didn’t touch the COBOL. Didn’t modify a single line of code. It copied a file in, let the batch do its job, and read what came out. The only thing new here is that someone wrote down what they expected before they looked at the answer.”

Linda’s eyes flicked to the terminal. She read the Gherkin. She could read it because it was English.

For a fraction of a second, something crossed her face that wasn’t anger.

It was recognition.

She knew those tax rules. She knew what Detroit city tax should be on a thousand dollars of gross pay. She knew why it might come out wrong. And she knew that a tool that could ask the question in plain English and get a plain answer was not a threat to the batch.

It was a threat to her.

Worse, it threatened the arrangement that had let everybody live with half-certainty for years. If Linda said the number was wrong, she owned the confession. If she said it was right and Ethan proved otherwise, she owned that too. Much safer to hold caution like a professional virtue and wait for somebody with a bigger title to call the thing by its name.

“We’ve managed these runs very carefully for a long time,” Linda said.

Ethan met her gaze. “I know. That’s why I’m here.”

Linda turned and walked back to her desk. Her heels clicked on the floor like a clock counting down.

Nathan watched her go.

He didn’t follow.

He didn’t know how to anymore.

Tuesday, 15:03 — The Staging Lie

Server room with a half-open rack and a tangle of cables. Nathan Cole kneels on the floor in worn chinos, sleeves rolled up, tracing a network cable through a rats' nest of wiring behind the rack. Ethan Carter stands beside him with a notepad, hoodie zipped up, face lit by a monitor glow. An old Windows Server tower sits on a shelf with a handwritten label: 'TEST???'. A whiteboard nearby shows scribbled IP addresses and passwords crossed out. Derek Lawson's dress shoes and suit pant legs visible in the doorway, his posture rigid and offended by dust. Fluorescent lights, warm humming room.
"Every place Ethan had ever worked had a staging environment."

Every place Ethan had ever worked had a staging environment. The concept was simple: a copy of the real system where you verified changes before they hit production. You pushed code to staging, watched it behave, confirmed nothing broke, then pushed it live. In 2026 the word had become inseparable from deployment pipelines and cloud infrastructure. SaaS companies ran staging environments that spun up automatically with every code change, tested themselves, and vanished when they were done. Even small shops had something. A second server. A virtual machine. A Docker container on someone’s laptop. Anything that let you answer the question: does this change work before a real person depends on it?

It didn’t have to be fancy. It had to exist.

Here, it didn’t.

That was the truth nobody had named until yesterday.

The room was hotter than it should’ve been. Not a comforting warmth. A sealed, humming heat that stuck to Nathan’s skin. The air tasted like dust and warmed plastic and decades of deferred decisions.

They had a room full of machines and a set of stories people told each other so they could sleep.

Nathan called one machine “test” because it made the calendar look less insane.

The machine didn’t agree.

Now Nathan was on the floor, tracing a network cable through the rats’ nest behind the rack. Three machines, six cables, zero labels. He was trying to figure out which box was plugged into which network port, because somebody had moved things around two years ago and nobody had updated the whiteboard. His knees hurt. His back hurt. The fluorescent buzz above them made his molars ache.

“The SQL collation is different,” Nathan muttered, reading a setting off a screen.

Ethan looked up from his notepad. “Different how?”

“The live server sorts text one way. This box sorts it another.” Nathan pulled himself up from the floor and pointed at the screen. “Collation is the rule the database uses to decide what order things go in. Whether uppercase and lowercase matter. It affects every query, every lookup, every report. The live system uses SQL_Latin1_General_CP1_CI_AS. This machine is set to SQL_Latin1_General_CP1_CS_AS.”

He said it like he was reading a patient’s chart to a doctor who’d never met the patient.

“One letter different,” Nathan continued. “‘CI’ means case-insensitive. ‘CS’ means case-sensitive. On the live system, ‘DETROIT’ and ‘Detroit’ and ‘detroit’ are all the same city. On this box, they’re three different cities. The VB6 clients sent everything in all caps. The batch stores it that way. But if a query uses mixed case, or if test data goes in lowercase, the results diverge. A lookup that finds a record on live returns nothing here.”

“So every test we’ve ever run on this machine…” Ethan started.

“Was answering a different question than we thought,” Nathan finished.

Ethan wrote it down.

The pen scratched on paper, loud in the small room.

Nathan felt something twist in his chest. Nobody wrote these things down. Not because they hated documentation. Because writing it down made it real. And real made it harder to ignore.

“That also means our Cucumber results might be lying to us,” Ethan said. Not angry. Matter-of-fact. “If the test server doesn’t behave like the live system, we don’t know whether a failure is a COBOL bug or an environment bug.”

Nathan nodded. He’d been thinking the same thing since yesterday’s run. The four-dollar discrepancy on Detroit city tax. What if the COBOL logic was correct and the test server was the liar?

“We need to fix this box first,” Ethan said. “Same SQL collation, same Windows regional settings, same COBOL runtime version. Otherwise every test we write is built on sand.”

Derek Lawson appeared in the doorway like he’d been summoned by the word “server.”

He didn’t step fully in. He hovered, offended by the dust and the cables and the fact that reality had the audacity to be physical.

“What exactly are we doing in here?” Derek asked.

Nathan kept his eyes on the screen. “Figuring out why test isn’t test.”

Derek’s jaw tightened.

“That room is sensitive,” Derek said. “We have vendors in and out. We have audit obligations. I need to understand why we’re opening things up.”

Ethan looked at him. His expression was polite. His eyes were not.

“This is compliance,” Ethan said. “Right now you’re compliant because Nathan memorizes the building. If Nathan gets sick on a Wednesday, you have no compliance. You have faith.”

Derek blinked.

He didn’t like being told the truth by someone who didn’t have a title.

“We don’t need this becoming a science project,” Derek said.

Ethan nodded once, slow. “Good. Then let’s stop doing archaeology in the live system.”

Nathan waited for Derek to explode.

Derek didn’t. Derek swallowed the irritation and substituted a smile.

“Fine,” Derek said. “But let’s be disciplined about scope. No downtime. No surprises. Keep me updated.”

He left. His shoes clicked down the hallway like a metronome.

Nathan listened until the sound faded.

In that silence, he could hear the server rack breathing.

Ethan looked back at Nathan.

“We build a staging environment,” Ethan said. “Real staging. Same as the live system. Then we run the Cucumber suite against it every time someone asks whether the batch is doing the right thing.”

Nathan shook his head automatically.

It wasn’t disagreement. It was trauma.

“They’ve tried,” Nathan said. “Every time someone tries, Derek says yes until he gets uncomfortable. Then he pulls the plug and calls it risk management. Then we’re back here. Me. Alone. At 02:18.”

Ethan listened.

Then he said, quietly, “Then we make it small enough that he can’t justify killing it.”

Nathan stared at him.

In Nathan’s head, a list of failed attempts rose up like ghosts.

In Ethan’s voice, the ghosts sounded less convincing.

Wednesday, 18:26 — The Number

Conference room with a whiteboard showing two boxes drawn in marker: 'LIVE SYSTEM' and 'STAGING' with an arrow between them labelled 'Same SQL, same COBOL, same folders'. Below the boxes, a list: 'MI ✗  OH ✓  PA ✗  IN ✓' with the failures circled in red. Ethan Carter stands by the whiteboard in a t-shirt, marker in hand. Nathan Cole sits forward in his chair, elbows on table, eyes wide despite exhaustion. Caleb Turner is grinning. Olivia Parker has her notebook open. Ryan Mitchell watches the whiteboard, half-smiling. Linda Pritchard sits stiffly with her binder, Sharon Mills beside her with glasses on a chain, Donna Reeves with a notebook clenched tight. Stale donuts on the table. Dark outside.
"The air smelled like sugar and burned coffee and the faint sourness of yesterday's panic."

The air smelled like sugar and burned coffee and the faint sourness of yesterday’s panic.

Ethan had spent Tuesday and Wednesday fixing the test server with Nathan. Same SQL collation. Same Windows regional settings. Same COBOL runtime. The machine now matched the live system closely enough that Ethan trusted it to tell the truth.

He’d run the Cucumber suite again after the fix.

The Detroit city tax scenario still failed. Expected $18.40, got $14.40. Same numbers. Same discrepancy.

That meant the failure wasn’t an environment lie. It was real. The COBOL batch was calculating Detroit city tax wrong. Had been calculating it wrong for years. Nobody had caught it because nobody had written down what the answer should be before looking at what the answer was.

That was Tuesday’s revelation. Today’s was different.

Ethan pointed at the whiteboard.

Two boxes. LIVE SYSTEM. STAGING. An arrow between them.

“We now have a staging environment that behaves like the live system,” Ethan said. “Same SQL, same COBOL runtime, same folder structure. When we run a Cucumber scenario against staging and it fails, the failure is real. Not environmental noise.”

Caleb leaned forward. “How many scenarios do we have?”

“Four,” Ethan said. “State tax for Michigan, Ohio, Pennsylvania, and Indiana. Two pass. Two fail.”

Two failures in four scenarios. Fifty percent. Nathan felt his jaw clench.

Not because the number surprised him. Because the number was visible.

Ethan circled the two failures in red marker. Michigan. Pennsylvania. Two states where the COBOL batch was producing wrong numbers. Two states where clients had been calling to complain and Linda had been saying “it’s always been that way.”

Now the whiteboard said otherwise.

Sharon Mills stared at the list. Her hand drifted toward her glasses chain the way it always did when she was nervous.

“Those have been running for years,” Sharon said. “Clients would have told us.”

“Clients did tell you,” Ethan said. “Nathan fixed it by hand at 02:00. The complaints stopped because someone absorbed them. Not because the problem went away.”

Sharon’s mouth opened. Then closed. Nathan could almost see the thought move behind her eyes: if this were truly serious, Linda would already be saying so more plainly. Sharon used Linda’s restraint the same way Linda used the old binders, as borrowed certainty.

Donna’s voice came out tight. “So what are you saying? That we’ve been wrong?”

She didn’t mean to sound scared. She was.

Ethan didn’t point at anyone. He pointed at the whiteboard.

“I’m saying the batch produces numbers. Now we can ask whether those numbers are right. Before this week, nobody could ask that question and get an honest answer. The answer was always whatever Nathan caught at 02:00.”

Nathan felt heat rise behind his eyes.

Not tears. The other thing. The feeling you get when someone says the sentence you’ve been trying to assemble for ten years.

He thought of his kids’ faces in the morning. The way he kissed foreheads while his mind was still reviewing the batch window. The way his wife’s eyes tracked his phone during dinner.

An honest answer, he thought. Not Nathan. Not at 02:00. An honest answer at 11:00 on a Monday morning.

Olivia looked at Nathan and saw it. She didn’t say anything. She nodded once, small.

Her hand moved automatically to the phone beside her notebook, not to check it yet, just to feel where it was. Ryan rubbed his thumb over his wedding band and kept his eyes on the whiteboard, but something in his face had tightened. Nathan wasn’t the only one in the room hearing a cost inside Ethan’s words.

Ryan leaned back and exhaled. “So we keep writing scenarios. Every tax rule we know about. Every edge case. Build up a library.”

“That’s the idea,” Ethan said. “Every scenario is a question the system has to answer. The more questions we ask, the less we depend on someone staying up all night to catch the ones it gets wrong.”

Linda’s chair creaked as she shifted.

She didn’t raise her hand. She didn’t need permission.

“And what about the COBOL?” Linda asked.

The room tightened.

Linda heard her own voice and hated that it shook at the edges. The COBOL was Thomas Whitaker’s ghost. It was also her paycheck.

Ethan let the question sit there because it deserved to.

“The COBOL stays,” he said finally. “For now. We don’t rewrite it. We wrap it. The Cucumber harness tests its outputs without touching its code. We treat it like a machine that works but can’t explain itself.”

Linda’s eyes narrowed. “You don’t trust it?”

Ethan met her gaze. “I trust it the way you trust a fifty-year machine that has to run every night. I trust it because it has survived. I don’t trust it to be understandable. That’s why we’re writing the understanding down. In English. Where everyone can read it.”

Nathan saw the moment Linda understood what was happening.

Not the whiteboard. Not the staging server.

The direction.

The end of gatekeeping.

Linda’s mouth tightened. Sharon stared at her hands. Donna looked at the whiteboard like it was a verdict. None of them looked at the others long enough to admit they were all waiting for one of the others to decide what the verdict meant.

Ethan capped the marker.

“Nothing changed today for your customers,” he said. “Batches will run tonight. Paychecks will go out Friday. I’m not breaking your system.”

He paused.

“I’m teaching it to explain itself.”

Thursday, 02:12 — The Window

Late-night office, Nathan Cole alone at his desk lit by monitor glow. A printed COBOL output report is laid out on the desk with highlighted rows. Nathan Cole: eyes red from fatigue, coffee cup in hand, one finger tracing a line item on the report. A manila folder with handwritten label 'MI CASES' sits open beside his keyboard. Wall clock shows 02:12. Outside: streetlights on wet pavement, rain still falling. The hum of servers in the background. The chair beside Nathan's desk is empty.
"At 02:12, Nathan was alone."

At 02:12, Nathan was alone.

He was always alone at 02:12.

The building felt smaller at night. Corners sharper. Every sound louder because there were fewer voices to drown them out. The server hum lived under his skin. His eyes burned from staring at logs too long, and his shoulders ached from being tensed for months.

Ethan had left at 17:30. Like a normal person. Like someone whose marriage wasn’t held together by the same thread that held the batch together.

At 18:07 Nathan had texted that he was on his way.

At 20:43 he had sent a second message.

Sorry. Still here.

Nobody answered the second one.

Nathan stared at a report on his desk. A familiar enemy. Numbers with jurisdiction codes that looked like abbreviations for sins. He could feel the codes in his mouth like bitter words. Some meant states. Some meant cities. Some meant rules nobody remembered until the IRS did.

One case from three months ago. Client in Michigan. One employee. Two municipal taxes. One union local dues rule. The file came in late, got processed in the next run. The withholding shifted by four dollars. Four. The client called and said the system was wrong. Linda said it was right because it’s always been that way.

Nathan had fixed it by hand. At 02:00. Like he always did.

Four dollars.

In a healthy system, four dollars is a rounding error. In payroll, four dollars is a lawsuit waiting for a calendar.

He opened a drawer and pulled out a manila folder. Tabs labeled by month. Paper-clipped stacks of flat-text printouts. He found the Michigan case and held it under the desk lamp.

Fixed-width columns. Employee ID, name, jurisdiction, hours, rate. A real person’s paycheck. A real person who got four dollars less than they should have because Thomas Whitaker had coded something in 1997 and nobody could prove it was wrong.

Until this week.

Nathan looked at the empty chair beside his desk. The chair Ethan sat in during the day, laptop open, hoodie up, typing Cucumber scenarios in a language Linda could read.

He could build a scenario from this case. He knew the format now. He’d watched Ethan do it four times. Given a payroll file. When the batch processes it. Then the numbers should be this. He could write it himself, in English, and let the harness ask the question.

But that wasn’t the point.

The point was whether he would show the folder to Ethan in the morning.

The old reflex fought him. The habit of protecting the system by keeping everyone else away from it. The habit that said if you let someone else see the ugly parts, they’ll panic and make decisions. Decisions made by people who don’t understand what they’re touching. Decisions that break the batch on a Wednesday and leave 5,000 people without a paycheck on Friday.

Nathan sat in the dark office with the folder on his desk and listened to the batch running on the server down the hall.

At 02:18, the scheduled task fired. The COBOL executable that Thomas Whitaker had compiled with Micro Focus sometime in the late 1990s processed another night’s worth of payroll. Hundreds of client files. Five thousand employees across three states. Files in. Numbers out. No one checking. No one asking. Just Nathan, awake, alone, absorbing whatever went wrong so that nobody else had to know.

The batch ran for thirty-seven minutes. Nathan sat through every one of them, watching the log scroll, drinking coffee that had gone cold twenty minutes ago.

At 02:55, the batch finished. Green status. No errors in the log.

No errors didn’t mean no errors. It meant no errors the system knew how to report. The four-dollar ghost would be in there somewhere, hiding in the output, invisible until a client called and Linda said it was always that way.

Nathan put the folder in his bag.

He drove home in the rain. His wife was asleep. His kids were asleep. The house was quiet the way houses are quiet when the person who lives there is never home enough for the silence to feel comfortable.

He set his alarm for 06:30 and lay in the dark.

At 08:47, he was back at his desk. Ethan arrived at 09:00, coffee in hand, hoodie unzipped.

Nathan slid the manila folder across the desk before Ethan sat down.

“This is the one,” Nathan said.

Ethan looked at the folder, then at Nathan. He didn’t ask why Nathan had brought it in. He didn’t ask what it cost Nathan to hand it over. He just sat down and opened it.

He studied the fixed-width columns. Employee ID, name, jurisdiction, hours, rate. Real data. A real person’s paycheck.

“We can build a scenario around this,” Ethan said. “Not the real name. We change the identifiers. Keep the numbers.”

He opened his laptop and navigated to the harness folder. Four feature files now, up from one on Monday. Four days. Four living documents that described what the COBOL batch should do in plain English.

Ethan created a new file.

michigan_municipal.feature.

He typed:

Feature: Michigan municipal tax with union dues
  Late-arriving files that cross processing windows
  must calculate city tax and union deductions correctly
  regardless of when the batch picks them up.

  Scenario: Late file for employee with Detroit city tax and union local dues
    Given a payroll file for client "Great Lakes Staffing"
    And an employee in "Detroit, MI" who worked 38 hours at $22.50
    And the employee has union local dues of $12.00 per pay period
    And the file arrived after the 22:00 cutoff
    When the batch processes the incoming file
    Then the gross pay should be $855.00
    And the MI state withholding should be $36.34
    And the Detroit city tax should be $20.52
    And the union dues deduction should be $12.00

Nathan read the scenario.

He read it the way Linda read her binder. Word by word. Looking for the lie.

“The union dues,” Nathan said. “That’s a flat deduction. Should come off before city tax calculation or after?”

Ethan looked at him. “You tell me.”

Nathan rubbed his face. His stubble dragged across his palm. He’d slept four hours.

“After,” he said. “City tax is calculated on gross pay minus pre-tax deductions. Union dues are post-tax. At least that’s what the COBOL does.”

“Is that what it should do?”

Nathan stared at him.

That was the question. The question nobody asked because asking it meant admitting you might have been doing it wrong for twenty years.

“That’s what Linda would say,” Nathan said quietly. “Whether it matches the actual Michigan tax code…”

He trailed off.

Ethan saved the feature file. Created a new fixture: great_lakes_staffing.dat. Typed in the employee record. Thirty-eight hours at twenty-two fifty. Detroit jurisdiction. Union local dues flag set.

The data was based on the real case from Nathan’s folder, with the names changed and the employee ID scrambled. Same hours. Same rate. Same jurisdictions. Same deduction codes.

“Ready?” Ethan said.

Nathan nodded.

Ethan typed:

cucumber features/michigan_municipal.feature

The terminal went quiet. Cucumber loaded. Found the feature file. Matched the Given steps to their Ruby definitions. The Ruby copied the fixture file to INCOMING on the staging server. Triggered the batch. The cursor blinked.

The office was awake around them now. Keyboards clicking in the next room. Someone’s phone ringing. The coffeemaker gurgling. Normal sounds. Daylight sounds. The batch was running at 09:14 on a Thursday morning because Nathan had carried a manila folder home at 02:23 and brought it back at 08:47.

Five minutes passed. Six. Caleb drifted over but didn’t interrupt.

Then the output appeared.

  Scenario: Late file for employee with Detroit city tax and union local dues
    Given a payroll file for client "Great Lakes Staffing"
    And an employee in "Detroit, MI" who worked 38 hours at $22.50
    And the employee has union local dues of $12.00 per pay period
    And the file arrived after the 22:00 cutoff
    When the batch processes the incoming file
    Then the gross pay should be $855.00
    And the MI state withholding should be $36.34
    And the Detroit city tax should be $20.52
      expected: 20.52
           got: 16.52 (FAILED)
    And the union dues deduction should be $12.00

1 scenario (1 failed)
8 steps (1 failed, 1 skipped, 6 passed)
5m41.203s

FAILED.

Four dollars off again. Different employee. Different hours. Different rate. Same discrepancy. The Detroit city tax was $4.00 short of what the math said it should be.

Nathan’s breath came out ragged.

Not a coincidence. Not a fluke. A pattern. A four-dollar ghost hiding inside the COBOL for years.

“Now we know,” Nathan said. His voice was barely above a whisper. “It’s not rounding. It’s not the file timing. The batch is subtracting something. Four dollars. Every time.”

Ethan nodded. “Could be a flat exemption that’s hardcoded somewhere. A per-employee deduction that was correct twenty years ago and nobody updated.”

Nathan laughed, small and broken.

“That sounds exactly like something Thomas would have done,” Nathan said. “Code a rule in 1997 and forget to tell anyone.”

He stared at the word on the screen. FAILED. A word he’d spent his career avoiding. A word that meant the batch was wrong, that Linda’s binder was wrong, that the system everyone trusted at 02:18 had been quietly miscalculating Detroit city tax for God knows how long.

The failure wasn’t a threat.

It was permission.

Permission to stop pretending the system was sacred. Permission to say out loud what Nathan had known in his bones: something was wrong, and the only reason nobody had fixed it was that nobody could prove it before the batch finished and the numbers disappeared into paychecks.

Now the proof was on screen. In English. Reproducible. At 09:20 on a Thursday morning, in daylight, where anyone could see it.

“Now we can talk about what ‘always been that way’ actually means,” Ethan said.

Nathan stared at the terminal.

Outside, the rain had stopped. Thin sunlight cut through the clouds for the first time all week.

Inside, for the first time in years, Nathan felt the system becoming something other than a hostage situation.

He also felt, with sick clarity, why this would get Ethan fired.

Friday, 16:49 — The Librarians

Break room with a humming vending machine and a small round table. Linda Pritchard: dark cardigan, skirt, sensible flats, binder open, pen tapping. Sharon Mills: beige blazer, patterned blouse, glasses on a chain, hands wrapped around a paper cup. Donna Reeves: navy dress, cardigan, clutching a printed Cucumber output report with highlighted FAILED lines, knuckles white. Window shows overcast sky and wet parking lot. Harsh fluorescent lighting.
"Linda Pritchard had spent three decades turning chaos into procedure."

Linda Pritchard had spent three decades turning chaos into procedure.

Procedure was her only real authority.

Titles came and went. Owners died. Platforms expired.

Procedure stayed.

She could survive almost anything as long as the rules lived in her binder and the knowledge lived in her head.

Sharon sipped coffee that tasted like burnt paper and didn’t complain because complaining didn’t change anything.

The vending machine hummed behind her with the steady confidence of something that only had one job.

Donna unfolded a printout and smoothed it flat. Her fingertips were dry from paper. Her hands didn’t know what to do when they weren’t holding something that told her what was true.

This printout wasn’t from her. This printout was from Ethan.

She’d found it on the shared printer. A Cucumber output report. Scenarios. Given. When. Then. FAILED. Plain English describing what the COBOL batch should calculate for Detroit city tax, and plain English saying it got the number wrong.

“He’s writing tests,” Donna said.

Sharon’s mouth tightened. “I saw.”

“Not tests like the programmers do,” Donna said. Her voice had a tremor she couldn’t control. “I can read these. They’re in English. They describe the tax rules.”

Linda’s pen stopped tapping.

She looked up.

The fluorescent lights made her skin look gray.

“I know,” Linda said.

“Anyone could read them,” Donna repeated. As if saying it again would make it less terrifying. “Caleb was showing Olivia. Ryan was reading over his shoulder. They were talking about Michigan city tax like they understood it.”

Sharon set her cup down. “They don’t understand it. Not really. There are hundreds of jurisdictions. Thousands of rules.”

“They don’t need to understand all of it,” Linda said. “They just need enough language to start forming conclusions from a few lines on a screen.”

The sentence sat between them like a stone.

They’d gotten some wrong. They all knew it. The binders had inconsistencies. The rules shifted between jurisdictions, between years, between interpretations made under pressure at 03:00. Some of those interpretations had been right. Some had been close enough. Some had been wrong and nobody had caught them because the only people who could check were the same people who’d made the call.

That was the trap. Each of them carried a private archive of moments that had not sat right. A withholding that looked light. A city code that felt off. A deduction explained away because the batch had already run and somebody important wanted the day to keep moving. None of them trusted her own memory enough to drag it into the open without cover.

Now a tool was checking. In English. Automatically. The same check every time.

Donna’s voice shook. “He showed up Monday. It’s Friday. Five days. He has five scenarios that test the batch without opening the COBOL, without touching VB6, without asking us anything.”

Linda heard the word and tasted metal.

Without asking us.

That was the threat. Not the tool. Not the Ruby code. Not the Gherkin syntax.

The fact that Ethan could test the system’s output without asking Linda, Sharon, or Donna what the answer should be.

He could write the expected values himself. Look them up. Calculate them from the published tax tables. Compare them against what the batch actually produced. And when the numbers didn’t match, the screen said FAILED, and then someone would come to Linda’s desk and ask why.

They’d come with evidence.

Not confusion. Not a phone call from an angry customer. Not a vague sense that something was off.

Evidence. In English. Repeatable.

The moat wasn’t just draining. It was being documented.

Sharon stared at her cup. Her eyes glistened.

“You think Nathan’s going to stop him?” Sharon asked.

Linda’s expression tightened.

“Nathan’s tired,” Linda said. “Nathan has kids. Nathan wants sleep. He may not be in a position to question something that looks like help.”

What she did not say was the rest of the calculation: Derek would never make a technical judgment on his own if Linda sounded uncertain, and Graham would never overrule the loyal women from Thomas Whitaker’s era if Derek kept sounding measured. Everyone above them was waiting for expertise. Everyone in this room was waiting for authority. That was how bad numbers survived respectable people.

Donna looked away fast, ashamed of how hard her own heartbeat was pounding.

“And what happens to us?” Donna asked.

She hated the tremor.

She hated that she needed the answer.

Linda didn’t answer immediately.

Not because she didn’t know. Because saying it out loud made it true.

“We stop being the first place those questions have to pass through,” Linda said.

And if they weren’t the only ones who knew, they were just women in their late forties and early fifties with a dead skill set and a mortgage and no polite way to admit it.

Linda closed her binder with a soft thud.

“We can’t stop the future,” Linda said.

Then she corrected herself.

“But we may still have some say in pace.”

Linda heard the words leave her mouth and tasted metal. She didn’t feel like a villain. She felt like a cornered animal doing math.

Outside the break room window, the parking lot reflected the sky like a dirty mirror.

Inside, the moat drained.

One scenario at a time.

Next Episode: "The Run Tells the Truth" Ethan turns the harness into a machine that refuses to lie. Every change triggers the Cucumber suite. The batch explains itself after every run. Management will call it progress until the truth points at them.
×
×