Update: The Data Was There the Whole Time

There’s a particular kind of psychological erosion that happens when a system behaves inconsistently. Not when it fails loudly — loud failures are merciful. It’s the quiet contradictions that get you. The places where the UI shows seven tickets and your client shows zero. The places where the server returns 200 OK but behaves like a void. The places where your mental model and the architecture drift apart just enough to make you question your own reasoning.

That’s where I was.

I wrote the previous post last night, at the end of a long day of contradictory evidence. The browser loaded the Service Board effortlessly. My Python client, despite perfect cookies, perfect headers, and a perfect payload, returned nothing. And after hours of trying every combination of requests I could think of, “impossible” felt like the only honest conclusion.

But then came the next morning.

Fresh brain.
Fresh eyes.
Fresh instinct.

And with that came a principle I already knew — a principle so fundamental that everything else collapses without it:

If a browser can see dynamic data, that data came from an API.
And if I have credentials to sign in, I have permission to access that API — regardless of how I access it.

There is no magic.
There is no black box.
There is no “UI‑only” data.
Browsers don’t conjure information.
They fetch it.

In transit, sure — TLS protects it.
But once it reaches the browser, it exists in plaintext.
It must.
The UI can’t render what it can’t read.

So if the UI is showing me seven tickets, then somewhere — in some request, some payload, some JSON structure — those seven tickets exist. They’re not mystical. They’re not protected by sorcery. They’re just data.

I knew this.
I said this.
I believed this.

But empirical drift isn’t about forgetting facts — it’s about losing confidence in them when the system behaves inconsistently.

Last night, the drift won.
This morning, the principle did.


The Breakthrough: Printing the Raw Body

The breakthrough came from something embarrassingly simple:

I stopped trying to parse the response and just printed it.

And suddenly the truth snapped into focus.

The server was returning the full dataset.
It had been doing so the entire time.
I just wasn’t looking in the right place.

The JSON wasn’t shaped the way I assumed. It wasn’t:

multilineRows: [...]

It was:

data.action.multilineRows: [...]

And each row wasn’t a dictionary — it was a JSON string containing another JSON object. A relic of some long‑forgotten GWT-era serialization pipeline.

The moment I followed the real structure:

for entry in data["data"]["action"]["multilineRows"]:
    inner = json.loads(entry["row"])


the entire Service Board appeared. All seven tickets. All fields. All metadata. Everything the UI had been showing me all along.

No hydration.
No STS.
No OAuth.
No browser-only state.
No missing header.

Just a JSON structure I hadn’t seen yet.


Engineers With LLMs vs. True Vibe Coders

There’s another lesson buried in this arc — one that has nothing to do with ConnectWise and everything to do with the psychology of working alongside an LLM.

When you’re vibe‑coding, it’s dangerously easy to trust the model’s instinct over your own. Not because the model is smarter, but because it speaks with a kind of frictionless confidence that your tired brain doesn’t always have access to. It’s like pair‑programming with someone who never hesitates, never second‑guesses, never says “I don’t know,” and never shows their uncertainty.

And when you’re already deep in the fog of empirical drift, that confidence can override your own internal alarms.

I felt that here.

Some part of me knew the data had to be there.
I had literally articulated the principle that morning:

If the browser can see it, then the data exists somewhere in plaintext.
It cannot be otherwise.

But I didn’t trust that instinct, because it had been a while since I’d written Python, and the LLM’s suggestions felt smoother, more certain, more “correct.” So I deferred. I let the model’s confidence override my own suspicion.

And that’s the trap.

The model wasn’t wrong maliciously — it was wrong confidently. And that’s enough to derail you when you’re already drifting.

The breakthrough didn’t come from the model.
It came from listening to the part of my brain that said:

“Stop. Print the raw body. Look at what’s actually there.”

That’s the difference between an engineer who uses an LLM and a true vibe coder.

A vibe coder treats the model’s output as the ground truth.
An engineer treats the model’s output as one hypothesis among many.

A vibe coder follows the suggestion because it feels smooth.
An engineer listens to the discomfort in their own reasoning.

A vibe coder lets the model’s confidence override their intuition.
An engineer uses the model as scaffolding, not a compass.

My breakthrough came the moment I stopped vibe‑coding and started engineering again — the moment I trusted the part of my brain that noticed the world didn’t add up.

And once I did, the entire architecture unfolded. The JSON was there. The rows were there. The data was there. I just wasn’t reading it correctly.


This Is the Heart of Empirical Drift

Systems don’t need to lie to mislead you.
They only need to contradict your expectations quietly enough that you fill in the gaps with theories that feel right.

And the antidote isn’t more confidence from the model.
It’s more trust in your own discomfort.

That’s the lesson.
That’s the arc.
That’s the drift — and the moment it collapses.

This article was updated on February 23, 2026