Case Study 02 · Ruby on Rails · AI agents

Around 150 PRs in five months: incremental Rails modernization with AI agents.

I joined a large Ruby on Rails application that had evolved for years with almost no documentation. With Claude and Codex, I reconstructed system knowledge, made the development environment repeatable, and carried out incremental modernization through small, controlled changes.

View the RPI toolkit ↗Ruby on Rails · Claude + Codex · Linear · RPI
Case study cover featuring around 150 pull requests

Some of the hardest engineering work begins in systems whose architecture was never documented. In this project, modernization was not a one-time rewrite. It meant recovering system knowledge, building a repeatable delivery process, and incrementally moving selected areas of older code into a newer architecture.

Confidentiality note: the client and product are anonymized. The process, tools, and stated figures are based on the engagement; identifying details have been omitted.

The starting point: a large codebase without a map

The system had evolved for years without a practical architecture overview or a verified setup guide. Knowledge about dependencies and required services was scattered between the codebase and the experience of people working on the project. My first local setup took about eight hours, largely because older packages and dependencies had to be identified one by one.

In a system like this, the bottleneck is not typing speed but the quality of understanding. That is why the first goal was not a new feature. We first needed context that both engineers and agents could rely on.

Documentation you can execute

I directed agents as they analyzed the older and newer parts of the application. We mapped corresponding services and data structures, required servers, dependencies, and the local setup process. I stored the findings as Markdown documentation in a separate repository so it could be versioned like code and reused as shared context by engineers and agents.

The documentation had to pass a practical test: using it, an agent should be able to guide an engineer from a clean machine to a running application. When I later repeated the setup on another computer, it took about 40 minutes rather than eight hours of manually tracing dependencies. The documentation was complete only when the process could be reproduced.

A shared memory for engineers and agents

The RPI workflow also maintained a versioned knowledge base in the repository's thoughts/shared directory. Research, technical plans, notes, and handoffs created for one task did not disappear with the agent session. They were committed and shared with the rest of the development team.

Before researching a feature from scratch, an agent searched that shared context for earlier analysis of the same area. If another engineer had already documented the behavior, constraints, or implementation plan, the next agent could reuse that work and verify only what had changed. This reduced repeated codebase exploration, conserved a limited token budget, and gave developers a common source of historical context.

The implement_plan command completed the loop. It read an approved plan from thoughts/shared/plans, followed its phases and success criteria, recorded progress in the same document, and paused for human verification where the plan required it. Knowledge was therefore not only stored; it remained connected to implementation and validation.

Sebastian Tekieli presenting an engineering workflow during a team session
The agent workflow was part of everyday engineering practice: shared context, explicit plans, and human review rather than isolated prompting.

The importer: from input files to production in three weeks

One of the first major deliverables was a data importer. Data exported from another system arrived as CSV and JSON files. We had to understand both formats, describe the target structure, and prepare an explicit mapping that could be reviewed before anything was written.

Agents helped analyze the files and draft the mapping and import logic, but they did not decide whether real data was correct. A person with the appropriate access ran the actual import in staging first and then in production. Separating implementation from data validation allowed us to complete the production importer in three weeks without assigning final responsibility to an agent.

From priority to human review
  1. 01LinearThe task and acceptance criteria define the scope.
  2. 02/featureContext, research, plan, code, and tests.
  3. 03/review-prAn independent check of delivery, code, and risk.
  4. 04HumanReview the findings and decide what happens next.

Two distinct roles: implementation and adversarial review

Linear was the single source for tasks and priorities, which I handled one at a time. The process used two Claude commands from the open source RPI plugin available in claude-ruby-marketplace: feature and review-pr.

The feature command did not start by writing code. It first gathered requirements and acceptance criteria, searched thoughts/shared for relevant work already documented by other developers, and then collected any missing historical context, similar implementations, and analysis of the affected area. Only then did it produce a plan, code, and tests. After quality checks and CI, I ran a separate self-review before asking a human to review the pull request.

Self-review was a second pass with a different objective. It checked delivery against the task, tests, security risks, performance, and established application patterns. In practice, it caught issues such as N+1 queries, missed requirements, and solutions that diverged from the existing architecture. The agent raised concerns, but I judged their relevance and decided what to fix before human review.

Every new feature and pull request had to provide at least 80% coverage for the changed code. The threshold was part of the agents' instructions and one of the gates before review. From January through May 2026, I authored and owned around 150 pull requests. Agents supported analysis, implementation, and review, but authorship and responsibility for the changes remained mine.

Results

~150

pull requests from January to May 2026

80%

minimum coverage for changed code

3 weeks

from starting importer work to production

8 h → 40 min

repeat environment setup using the documentation

The project was too large to complete the full modernization during this period. I developed new features, refactored a substantial amount of older code, and incrementally moved selected areas into the newer architecture. The most important result was not a claim that the rewrite was complete, but a repeatable way to work more safely in a system that was initially difficult even to run.

Practices you can reuse

  • Documentation first: create shared, versioned context for engineers and agents before implementing the first change.
  • Small, frequent PRs: keep pull requests small enough to review and deploy independently.
  • AI as reviewer: separate implementation from self-review and have an agent look for gaps before human review.
  • Coverage as a gate: enforce minimum coverage for changed code on every pull request and review test quality as well.
  • One source of priorities: keep tasks and acceptance criteria in one place so every iteration starts from an agreed scope.

Your next step

Want to introduce AI-assisted engineering workflows to your team?

We can start with one process, design a controlled agent workflow, and agree on how to measure its effect in your codebase.

Explore CAAO

Chief AI Agents Officer

Let us start withone process.

Briefly describe what currently takes time or blocks the work. I will tell you whether there is a strong entry point for an AI agent and suggest the next step.

No tool pitch and no obligation. Your details are used only to respond to this request.