Every engineering team says they care about technical debt. Almost none of them have a system that catches it before merge. What they have instead is a backlog column called "Tech Debt" that grows quietly until a quarter gets set aside to "pay it down" — which really means six weeks of archaeology into code nobody remembers writing.
We built Codeward because we didn't want an ignored backlog column. We wanted a gate.
Debt is a PR-time problem, not a sprint-time problem
The moment technical debt is cheapest to fix is the exact moment it is created: inside the pull request, before a human reviewer has spent their attention budget checking whether the tests pass. Once a PR merges, the cost of fixing a bad abstraction, an untested edge case, or a copy-pasted utility function goes up by an order of magnitude, because now other code depends on it.
This is the core assumption behind Codeward's design: debt prevention has to happen at PR time, or it doesn't really happen. Everything downstream of merge is remediation, not prevention.
"Remediation is expensive, demoralizing, and constantly postponed. Prevention at PR review is instant, localized, and context-fresh."
What "catching it early" actually requires
Saying "catch debt in the PR phase" is easy. Building a system that does it reliably, without becoming the thing developers mute in Slack, is the hard part. Three conditions must hold simultaneously:
- 1. The analysis has to be fast enough to fit inside a normal review cycle. If a scan takes 40 minutes, developers merge before it finishes and the tool becomes decorative.
-
2. The findings have to be specific, not generic. "Consider refactoring this function" is useless noise. "This function duplicates the retry logic in
escalationQueue.ts— extract a sharedwithBackoff()helper" is actionable signal. - 3. The system has to know when not to flag something. A tool that flags everything gets ignored just as fast as a tool that flags nothing.
We run each PR through a set of specialized agents — not one monolithic linter, but focused reviewers, each responsible for a narrow domain (architecture consistency, code bloat, security posture, and more). Each agent runs inside an isolated sandbox per scan, so one PR's analysis can't leak into or interfere with another's, and a misbehaving scan can't affect the host system.
Why per-PR, not per-commit
An early design decision that mattered more than it looks: we trigger scans per pull request, not per commit.
Per-commit scanning sounds more thorough, but in practice it means re-analyzing the same code five times as a developer pushes fixups, which multiplies compute cost without multiplying insight. Per-PR scanning, combined with AI model fallbacks when a primary provider is degraded or rate-limited, keeps the system both affordable and fast enough to stay in the loop developers actually use.
This sounds like an infrastructure detail. It isn't — it's a debt-prevention decision. A scanning system that's too expensive to run on every PR gets scoped down to "only run on release branches," and the moment that happens, you're back to catching debt after it's already load-bearing.
Debt has categories, and they need different tools
"Technical debt" is often used as a catch-all, but the failure modes are distinct enough that a single generic pass misses most of them:
1. Bloat Debt
Dead code, duplicated logic, over-engineered abstractions for a problem that didn't need one.
2. Architectural Drift
A module quietly taking on responsibilities it shouldn't, breaking the boundaries a team agreed on.
3. Security Debt
Patterns that aren't a vulnerability today but will be the moment an assumption changes.
4. Correctness Debt
Code that works for the happy path and silently breaks under concurrent load or failure modes.
Trying to catch all four with one prompt to one model produces shallow findings across the board. Specialized agents, each scoped to one category, produce findings a human reviewer would actually trust enough to act on.
What happens when something is found
The output of a scan isn't a wall of comments. Findings are triaged, deduplicated, and — where they cross a severity threshold — escalated into a tracked GitHub issue rather than left as an ephemeral PR comment that disappears the moment the PR merges.
That escalation path is idempotent: the same underlying issue found across multiple scan runs doesn't spawn five duplicate GitHub issues. It's fingerprinted once and tracked once.
That distinction matters more than it sounds. A tool that creates duplicate issues trains a team to ignore its output within two weeks. A tool that tracks findings precisely, once, becomes something engineers actually triage.
The real measure of success
We don't measure Codeward's value in "number of issues found." A tool optimized for finding a lot of issues is trivially easy to build and completely useless — it just shifts the debt from "in the code" to "in an ignored backlog."
The metric that matters is debt that never gets merged in the first place, which by definition is invisible in any after-the-fact dashboard. It shows up instead as:
- PRs that stay smaller and tighter
- Review cycles that stay hours, not days
- A codebase six months from now that doesn't need a "refactor sprint" because nothing was allowed to compound
Want to see what's hiding in your current PR queue? Codeward runs its first scan on your next pull request — no separate audit, no six-week engagement, just a gate that was always supposed to be there.