DEV Community

Agdal
Agdal

Posted on AI-assisted

What changed when I stopped using SOL for everything in Codex

I’ve been developing web sites and applications for years, and lately Codex has become a pretty big part of how I work.

At first my workflow was simple. Open the project, use SOL, explain what I want, let it inspect the code, implement the feature, run the tests, fix whatever breaks, and continue.

It worked.

The problem was that after a while I started noticing how much of SOL’s time was being spent on work that didn’t really require SOL.

A difficult architectural decision? Sure.

Trying to understand why a bug exists across several parts of the application? Absolutely.

But once a task was already understood and the important decisions had been made, a lot of the remaining work was fairly mechanical implementation.

Controllers. Validation. Services. Views. Tests. CSS. Small refactors.

Luna Max was perfectly capable of doing a lot of that work.

So I started changing the way I used the models.

Instead of asking SOL to think about the problem and then also spend the rest of the session implementing everything, I started asking SOL to prepare the work for Luna.

That sounds like a very small change.

It ended up changing most of my Codex workflow.

The real problem wasn’t code generation

One thing I quickly discovered was that telling SOL to “make a plan” wasn’t enough.

Codex can produce plans that look perfectly reasonable while you’re reading them.

Then another model actually tries to implement the plan and you realize how much information is missing.

“Add validation.”

“Update the controller.”

“Add tests.”

“Handle errors.”

Technically those are steps.

They just aren’t necessarily useful instructions.

On a real application, the important questions are usually somewhere underneath those sentences.

Which existing service owns this behavior?

Which business rules must remain unchanged?

What happens when the input is invalid?

Which existing tests represent behavior we are not allowed to break?

Does this require a new migration, or can the existing model support it?

What should the implementation model do if the repository does not look the way the plan expected?

Those are the decisions that matter.

So the workflow gradually became less about asking SOL for a generic plan and more about getting SOL to understand the actual project first.

On an existing project, that means inspecting the real repository, relevant code, tests, routes, schema and current architecture before planning anything.

On a new project, there obviously isn’t a repository to inspect yet, so the process starts earlier: discovery, requirements, specification and architecture.

Only after that does implementation planning make much sense.

SOL plans. Luna implements.

Eventually I ended up with a fairly simple division of responsibilities.

SOL handles the work where stronger reasoning is useful.

Luna handles as much of the actual implementation as possible once that reasoning has already been done.

The important part is that the plan shouldn’t become the implementation written in English.

I ran into that problem too.

If SOL writes an enormous plan containing almost every line Luna should eventually type, I haven’t really delegated much. SOL has already solved and practically implemented the feature, just in another format.

So I now try to keep a boundary between planning and implementation.

SOL should answer things like what needs to change, where it belongs, why it belongs there, what decisions are already locked, what constraints must be preserved, what failure cases matter and how we will verify that the result works.

Luna still has to write the actual code.

That distinction turned out to matter more than I expected.

The moment where AI agents usually make me nervous

There is another behavior I kept seeing on longer projects.

The implementation model receives a good plan, starts working through it, and eventually discovers something unexpected.

Maybe the existing architecture is slightly different.

Maybe a method mentioned in the plan doesn’t exist.

Maybe an earlier implementation decision changed the shape of the module.

At that point an AI coding agent has two choices.

It can stop and tell you that reality no longer matches the assumptions.

Or it can decide that it understands the intent well enough and redesign part of the solution itself.

The second option is where things can get ugly.

A seemingly reasonable local fix can quietly turn into a new architectural decision, followed by another decision required by that decision, and suddenly the agent is modifying parts of the application that were never part of the original task.

So one of the rules I started using is extremely simple:

If the plan materially conflicts with the real project, stop.

Don’t invent a new architecture just to keep moving.

Report what the plan assumed, what actually exists and what decision is now required.

Then the problem can go back to SOL if it genuinely requires stronger reasoning.

This slows down one individual step.

It has saved me a lot of time cleaning up “helpful” improvisation afterward.

I also stopped treating project context like chat history

Another thing that became annoying on longer projects was repeating myself.

What phase are we in?

What did we decide about this module?

Which plan is active?

What is Luna currently allowed to change?

Did we already approve this architecture?

Why did we decide not to use that dependency?

Which model should work next?

Chat history is a terrible place to keep all of that.

Sessions change. Context gets summarized. You start a new conversation. A model reads the code but doesn’t know why certain decisions were made.

I wanted the project itself to carry enough information for the next Codex session to understand where it was.

So I started keeping the workflow state inside the repository.

Not a giant journal of everything the AI ever did.

That would become useless almost immediately.

The state file only needs to answer where the project is now.

If Luna spends three hours implementing the same active plan and nothing meaningful changes, the state does not need to be updated every five minutes.

It changes when something meaningful happens: a handoff, a blocker, a STOP checkpoint, a review result, a takeover, acceptance of a task, moving to the next module.

The implementation details belong in the active plan and the code.

The state is just the navigator.

This eventually became TITAN

After using variations of this workflow for a while, I realized I was recreating the same structure on different projects.

So I put it into a repository and called it TITAN - Technical Intelligence, Tasking & AI Navigation.

The name sounds much more dramatic than what is actually inside it.

There is no runtime, no AI proxy and no orchestration server.

It is mostly Markdown.

Roles, workflow rules, project state, planning prompts, handoff rules and templates live inside the repository where Codex can read them.

That was intentional.

I didn’t want another black box between me and the model.

If a rule is stupid, I want to be able to open the file, read it and change it.

The normal flow is roughly SOL doing discovery and architecture when needed, SOL preparing the current implementation task, Luna implementing it, tests verifying the result, and then either continuing, reviewing or stopping when something requires a decision.

SOL can still take over implementation when Luna gets stuck on something that genuinely requires continuous high-level reasoning.

The point isn’t to artificially force every line of code through Luna.

The point is to stop paying for stronger reasoning when the task no longer needs stronger reasoning.

Is this just vibe coding with more paperwork?

Maybe that is the obvious question.

I don’t really think so, although the definition of “vibe coding” seems to change depending on who is using the term.

I’m not particularly interested in having an agent generate an application while I avoid understanding what it is doing.

The whole reason I ended up with this workflow is because longer AI-assisted projects became harder to control once architecture, business rules, state and multiple implementation sessions started interacting.

I still own the decisions.

I still review what gets built.

Tests still matter.

Production verification still matters.

And when the model says something that doesn’t make sense, the fact that it came from a stronger model doesn’t make it correct.

For me, AI-assisted development became much more useful when I stopped treating the model as one very fast developer that should do everything and started treating different stages of the work differently.

Has it actually saved anything?

In my own work, yes.

Before this I was using SOL for almost entire projects.

Once I started moving well-defined implementation work to Luna Max, my SOL usage dropped noticeably.

I also spend less of my own time repeatedly explaining project state, architecture and model handoffs.

What I do not have is a controlled benchmark.

I haven’t taken the same set of projects and scientifically compared SOL-only against SOL-to-Luna while measuring every token, cache effect, iteration and failure.

So I’m not going to claim that TITAN reduces token usage by some percentage.

It may not even reduce the raw number of tokens in every situation.

A planning pass itself costs tokens, and changing models has its own tradeoffs.

What I care about more is how much work actually needs to be done by the stronger reasoning model.

If SOL spends one good reasoning pass preparing a task and Luna can then handle a long edit-test-fix-test implementation loop, that has been worthwhile for me.

For a tiny change, it probably isn’t.

I wouldn’t use this process to change the text on a button.

What I want to find out now

TITAN works well enough for the way I use Codex that I decided to make it open source.

That doesn’t mean I think the methodology is finished.

Actually, the interesting part now is seeing where it fails for people who didn’t design it.

A few of the best changes already came from other developers questioning assumptions in the workflow.

One person pointed out that a planning model could “verify” an extremely detailed plan by temporarily implementing the feature, running the tests and reverting everything before handing the plan to Luna.

That is technically thorough.

It is also a spectacular waste of the handoff.

That feedback led to a new rule: SOL planning and review are application-code-read-only. If SOL genuinely needs to take over debugging or implementation, the workflow explicitly transitions into that role first.

That kind of feedback is much more useful to me than someone telling me the repository looks nice.

If anyone here uses Codex on projects that have grown beyond the toy-project stage, I’d be interested in seeing what happens when TITAN hits a codebase and workflow I had nothing to do with.

Especially if it gets annoying.

That is probably where the next useful rule is hiding.

The project is MIT licensed and available on GitHub:

https://github.com/netelite/titan

You can also initialize it directly inside a project folder with:

npx -y @netelite/titan@latest

That only adds the TITAN methodology files to the project. It does not replace your application code or add a framework dependency.

For a new project, open it in Codex with SOL and start with something as simple as:

Start this project using the TITAN methodology.

Idea:
<your idea>

For an existing project, SOL starts by understanding what is already there before planning changes.

If you try it, I’m much more interested in hearing where the workflow gets in your way than whether you agree with every rule.


Disclosure: I used AI assistance while drafting and editing this article and to help translate this article into English and to improve grammar and clarity. The workflow, project experience, opinions and TITAN methodology described here are my own, and I reviewed the final text before publication.

Top comments (0)