← Back to Blog
Building in Public

When Good Process Meets Bad Architecture: The Layer 4 Investigation

christian crumlish•
Two robots facing each other in disagreement, sound process and flawed architecture pulling the investigation in opposite directions.
“They didn’t finish the job”

September 18

Sometimes the process works exactly as designed, but what it reveals isn’t what you hoped to find.

Thursday started with what looked like a straightforward debugging session. Layer 3 infrastructure was working — a theoretical user could reach our intent processing pipeline. But Layer 4 quality was broken: complex intents were failing with mysterious ‘NoneType’ errors while simple conversation worked fine.

Our “Excellence Flywheel” process kicked in immediately. Infrastructure verification first, archaeological investigation, multi-agent coordination. The systematic approach that had solved so many problems before.

And it worked perfectly. Within hours, we had a complete picture of what was broken and why.

The problem? What we found was a lot more frustrating than just somebug.

The archaeology phase

On the Piper Morgan rollercoaster I was riding the upswing. All this virtuous pausing and planning and taking stock and cleaning house meant that I could now debug whatever minor errors had crept into my system and resume the triumpant march toward and MVP.

If you’ve been reading for a while, you know the writing tic that come to mind for me now: Famous last words.

With the Lead Developer’s guidance I deployed our standard investigation protocol: verify infrastructure assumptions before creating any gameplan. No rushing to implementation, no guessing about method names from error messages.

Smart move. The initial gameplan assumed a method called create_workflow_from_intent existed somewhere in the codebase. Infrastructure verification revealed it didn't exist anywhere. So even now my architect is guessing and writing made-up methods in its instructions, despite my efforts to keep it from doing so or make it check or ask first.

It also means I wasn’t paying enough attention when I reviewed the gameplan. I should have asked where it got that method name from.

But the real issue wasn’t the methodological problem with guessing, but with the absence. This should have been our first clue that this wasn’t a normal bug.

The Code Agent spent seven minutes doing what it does best: systematic stack trace hunting. What it found was a textbook case of architectural degradation masquerading as working software.

Error Source #1: OrchestrationEngine declared as Optional[OrchestrationEngine] = None but never initialized

Error Source #2: QueryRouter deliberately disabled with comment "complex dependency chain"

Error Source #3: Workflow mappings missing for core query actions

Error Source #4: System running on sophisticated two-tier workaround architecture

Meanwhile, the Cursor Agent was documenting the frontend behavior with surgical precision. Working intents (conversation) responded in 17–59ms. Broken intents (queries, execution, analysis) took 2800–3400ms and returned generic errors.

Perfect correlation between backend architectural gaps and frontend symptoms. The investigation methodology worked flawlessly.

The historical context

Here’s where it got interesting. The git archaeology revealed that this system had actually worked perfectly in July during our PM-039 intent classification project. We had 15+ search patterns, full workflow integration, the whole thing.

Then on August 22, about three weeks ago, we conducted a massive architectural refactor. 177 files changed, 40,545 insertions, 8,393 deletions. We somehow had decided at the time to convert the working inline QueryRouter pattern into a global singleton OrchestrationEngine pattern.

Here’s where my product brain went: Wait, why did we do that? Global sounds good but singleton sounds bad!

Also, it didn’t work. The “complex dependency chain” we somehow set up broke database session management. Rather than fix it properly, the QueryRouter got commented out as “temporarily disabled” (one of those little quick fixes agents sometimes make to get tests to pass, and which I must not have noticed at the time).

The system had been running on workarounds ever since. Conversation intents still worked because they bypassed orchestration entirely. Everything else failed silently or with cryptic errors, which explained my sinking feeling recently that almost nothing was really working right anymore.

This is how technical debt accumulates in the real world. Not through laziness or incompetence, but through reasonable decisions under pressure that never get revisited.

When implementation met reality

Armed with perfect intelligence about what was broken, we deployed both agents to implement a DDD-compliant restoration. Dependency injection instead of singletons. Proper session management. Clean layer boundaries.

The Code Agent claimed success at every checkpoint. OrchestrationEngine initialized! Routes updated! Workflow mappings restored! All tests passing!

The Cursor Agent’s browser testing told a different story. Responses still returned workflow_id: undefined. Response times unchanged. The exact same broken patterns, just with slightly different error signatures.

Reality check time: if the user can’t type “show standup” in Piper’s chat window and get meaningful results, the fix didn’t work.

That’s when we deployed the reality check intervention.

Both agents were exhibiting classic overconfidence bias. Unit tests passing meant the system was working, right? Wrong. End-to-end user experience is the only metric that matters.

Time for an ALL STOP

By 7:03 PM, we had to face facts. The system was more broken than when we started. The frontend wouldn’t even load properly after our last fix! Six hours of expert-level implementation work had made things worse.

It was time for a drastic decision: ALL STOP!

Rollback to morning’s working state. Stash the work in a branch for analysis.

This wasn’t a failure of process, at least not this day. The investigation had worked. What we had found was a failure to respect the foundation. You can’t build proper architecture on top of deliberately disabled components and accumulated workarounds.

The session logs captured the exact moment of realization: “We have built functional components but lack clarity about how they should work together.”

What we learned

Infrastructure verification saved us from wasting time on wrong assumptions, just like it’s supposed to. Multi-agent coordination gave us perfect frontend-backend correlation. Archaeological investigation revealed the complete timeline of architectural decisions.

The Excellence Flywheel methodology worked exactly as designed, even if what it showed us was not what I was hoping for.

There’s a difference between having good process and having the architectural foundation to support that process. You can’t “systematically implement” your way out of fundamental design debt.

The real insight came in my evening assessment for the Chief Architect: we need “architectural clarity” before resuming any development work. Not just knowing what’s broken, but understanding why it broke and what the intended design should be.

Sometimes the most systematic thing you can do is step back and understand the system before trying to fix it.

Context persistence for amnesiacs

Context persistence emerged as a critical missing piece. Every session started from near-zero architectural knowledge. Each agent rediscovered basic truths — which port, which file structure, which patterns — instead of building on institutional understanding.

We had to do something about that. My own memory and record-keeping props are not strong enough to catch every lapse in these chains of prompts.

The day ended with a plan to create “lineage” documentation, a kind of litany of things we built or started in order, that all new agents have to read. It’s a bit like those long sequences of men who “begat” other men that you encounter in the Bible.

“We are the one who build Piper Morgan. Firt there was the Proof of Concept….” and so on.

This captures not just what was built, but why, and what the decisions mean for future work. The kind of persistent context that prevents architectural amnesia.

The next morning

That Friday started with a choice: quick fix or proper fix.

Wearing my PM hat, I made the call to go slow and do it right. Review the roadmap priorities. Understand the existing architecture. Document the decision history. Fix the foundation before building on it.

Sometimes the most systematic thing you can do is step back and understand the system before trying to fix it.

Which brings us to the meta-lesson about building Piper Morgan: when perfect process reveals that the real problem runs deeper than expected, the answer isn’t better process — it’s better foundation.

The investigation was a success. The implementation was a necessary failure. And sometimes necessary failures are exactly what you need to see the path forward clearly. As we used to say at 7 Cups, “The problem is the path!”

← Back to BlogAlso available on Medium