Skip to content

The 3:1 Ratio

ctx

Scheduling Consolidation in AI Development

Jose Alekhinne / February 17, 2026

How often should you stop building and start cleaning?

Every developer knows technical debt exists. Every developer postpones dealing with it.

AI-assisted development makes the problem worse -- not because the AI writes bad code, but because it writes code so fast that drift accumulates before you notice.

In Refactoring with Intent, I mentioned a ratio that worked for me: 3:1. Three YOLO sessions create enough surface area to reveal patterns. The fourth session turns those patterns into structure.

That was an observation. This post is the evidence.


The Observation

During the first two weeks of building ctx, I noticed a rhythm in my own productivity. Feature sessions felt great: new commands, new capabilities, visible progress. But after three of them, things would start to feel sticky: variable names that almost made sense, files that had grown past their purpose, patterns that repeated without being formalized.

The fourth session -- when I stopped adding and started cleaning -- was always the most painful to start and the most satisfying to finish.

It was also the one that made the next three feature sessions faster.

The Evidence: Git History

The ctx git history between January 20 and February 7 tells a clear story when you categorize commits:

Week Feature commits Consolidation commits Ratio
Jan 20-26 18 5 3.6:1
Jan 27-Feb 1 14 6 2.3:1
Feb 1-7 15 35+ 0.4:1

The first week was pure YOLO. Almost four feature commits for every consolidation commit. The codebase grew fast.

The second week started to self-correct. The ratio dropped as refactoring sessions became necessary -- not scheduled, but forced by friction.

The third week inverted entirely. v0.3.0 was almost entirely consolidation: the skill migration, the sweep, the documentation standardization. Thirty-five quality commits against fifteen features.

The debt from weeks one and two was paid in week three.

The Compounding Problem

Consolidation debt compounds. Week one's drift doesn't just persist into week two -- it accelerates, because new features are built on top of drifted patterns.

By week three, the cost of consolidation was higher than it would have been if spread evenly.


What Drift Actually Looks Like

"Drift" sounds abstract. Here is what it looked like concretely in the ctx codebase after three weeks of feature-heavy development:

Predicate Naming

Convention says boolean functions should be named HasX, IsX, CanX. After three feature sprints:

// What accumulated:
func CheckIfEnabled() bool    // should be IsEnabled
func ValidateFormat() bool    // should be HasValidFormat
func TestConnection() bool    // should be CanConnect
func VerifyExists() bool      // should be Exists or HasFile
func EnsureReady() bool       // should be IsReady

Five violations. Not bugs -- but friction that compounds every time someone (human or AI) reads the code and has to infer the naming convention from inconsistent examples.

Magic Strings

// Week 1: acceptable prototype
if entry.Type == "task" {
    filename = "TASKS.md"
}

// Week 3: same pattern in 7+ files
// Now it's a maintenance liability

When the same literal appears in seven files, changing it means finding all seven. Missing one means a silent runtime bug. Constants exist to prevent exactly this -- but during feature velocity, nobody stops to extract them.

Refactoring with Intent documented the constants consolidation that cleaned this up. The 3:1 ratio is the practice that prevents it from accumulating again.

Hardcoded Permissions

os.WriteFile(path, data, 0644)  // 80+ instances
os.MkdirAll(path, 0755)         // scattered across packages

Eighty-plus instances of hardcoded file permissions. Not wrong -- but if we ever need to change the default (and we did, for hook scripts that need execute permissions), it means a codebase-wide search.

Drift Is Not Bugs

None of these are bugs. The code works. Tests pass.

But drift creates false confidence: the codebase looks consistent until you try to change something and discover that five different conventions exist for the same concept.


Why You Cannot Consolidate on Day One

The temptation is to front-load quality: write all the conventions, enforce all the checks, prevent all the drift before it happens.

This fails for two reasons.

First, you do not know what will drift. Predicate naming violations only become a convention check after you notice three different naming patterns competing. Magic strings only become a consolidation target after you change a literal and discover it exists in seven places.

The conventions emerge from the work. They cannot precede it.

This is what You Can't Import Expertise meant in practice: the consolidation checks grow from the project's own drift history. You cannot write them on day one because you do not yet know what will drift.

Second, premature consolidation slows discovery. During the prototyping phase, the goal is to explore the design space. Enforcing strict conventions on code that might be deleted tomorrow is waste. YOLO mode has its place -- the problem is not YOLO itself, but YOLO without scheduled cleanup.

The Consolidation Paradox

You need drift history to know what to consolidate.

You need consolidation to prevent drift from compounding.

The 3:1 ratio resolves this paradox: let drift accumulate for three sessions (enough to see patterns), then consolidate in the fourth (before the patterns become entrenched).


The Consolidation Skill

The ctx project now has a /consolidate skill that encodes nine project-specific checks:

Check What It Catches
Predicate naming Boolean functions not using Has/Is/Can
Magic strings Repeated literals not in config constants
File permissions Hardcoded 0644/0755 not using constants
Godoc style Missing or non-standard documentation
File length Files exceeding 400 lines
Large functions Functions exceeding 80 lines
Template drift Live skills diverging from templates
Import organization Non-standard import grouping
TODO/FIXME staleness Old markers that are no longer relevant

This is not a generic linter. These are project-specific conventions that emerged from ctx's own development history. A generic code quality tool would catch some of them. Only a project-specific check catches all of them -- because some of them (predicate naming, template drift) are conventions that exist nowhere except in this project's CONVENTIONS.md.


The Decision Matrix

Not all drift needs immediate consolidation. Here is the matrix I use:

Signal Action
Same literal in 3+ files Extract to constant
Same code block in 3+ places Extract to helper
Naming convention violated 5+ times Fix and document rule
File exceeds 400 lines Split by concern
Convention exists but is regularly violated Strengthen enforcement
Pattern exists only in one place Leave it alone
Code works but is "ugly" Leave it alone

The last two rows matter. Consolidation is about reducing maintenance cost, not achieving aesthetic perfection. Code that works and exists in one place does not benefit from consolidation -- it benefits from being left alone until it earns its refactoring.


Consolidation as Context Hygiene

There is a parallel between code consolidation and context management that became clear during the ctx development:

Code Consolidation Context Hygiene
Extract magic strings Archive completed tasks
Standardize naming Keep DECISIONS.md current
Remove dead code Compact old sessions
Update stale comments Review LEARNINGS.md for staleness
Check template drift Verify CONVENTIONS.md matches code

ctx compact does for context what consolidation does for code: it moves completed work to cold storage, keeping the active context clean and focused. The attention budget applies to both the AI's context window and the developer's mental model of the codebase.

When context files accumulate stale entries, the AI's attention is wasted on completed tasks and outdated conventions. When code accumulates drift, the developer's attention is wasted on inconsistencies that obscure the actual logic.

Both are solved by the same discipline: periodic, scheduled cleanup.

This is also why parallel agents make the problem harder, not easier. Three agents running simultaneously produce three sessions' worth of drift in one clock hour. The consolidation cadence needs to match the output rate, not the calendar.


The Practice

Here is how the 3:1 ratio works in practice for ctx development:

Sessions 1-3: Feature work

  • Add new capabilities
  • Write tests for new code
  • Do not stop for cleanup unless something is actively broken
  • Note drift as you see it (a comment, a task, a mental note)

Session 4: Consolidation

  • Run /consolidate to surface accumulated drift
  • Fix the highest-impact items first
  • Update CONVENTIONS.md if new patterns emerged
  • Archive completed tasks
  • Review LEARNINGS.md for anything that became a convention

The key insight is that session 4 is not optional. It is not "if we have time." It is scheduled with the same priority as feature work.

The cost of skipping it is not visible immediately. It becomes visible three sessions later, when the next consolidation session takes twice as long because the drift compounded.


What the Ratio Is Not

The 3:1 ratio is not a universal law. It is an empirical observation from one project with one developer working with AI assistance.

Different projects will have different ratios. A mature codebase with strong conventions might sustain 5:1 or higher. A greenfield prototype might need 2:1. A team of multiple developers with different styles might need 1:1.

The number is less important than the practice: consolidation is not a reaction to problems. It is a scheduled activity.

If you wait for drift to cause pain before consolidating, you have already paid the compounding cost.


If you remember one thing from this post...

Three sessions of building. One session of cleaning.

Not because the code is dirty -- but because drift compounds silently, and the only way to catch it is to look for it on a schedule.

The ratio is the schedule.


The Arc So Far

This post sits at a crossroads in the ctx story. Looking back:

And looking forward: the same principle applies to context files, to documentation, and to the merge debt that parallel agents produce. Drift is drift, whether it lives in code, in .context/, or in the gap between what your docs say and what your code does.

The ratio is the schedule. The schedule is the discipline.


This post was drafted from git log analysis of the ctx repository, mapping every commit from January 20 to February 7 into feature vs consolidation categories. The patterns described are drawn from the project's CONVENTIONS.md, LEARNINGS.md, and the /consolidate skill's check list.