MESHTEN LAB•Developer Tooling
October 22, 2026•Field Case Study

Find the Bug Class, Not the Bug

AI agents fixed a database cutover one symptom at a time, and one flow kept breaking. A syntax-aware census sized the whole class in one pass, and the guarded rewrite tool accepted four of the 777 calls it counted under its guards.

Core Finding:During a database cutover, AI agent lanes fixed bugs as they surfaced, one log entry per bug. The flow for creating a new worker account and signing that worker in appears in five related entries across two fix rounds, each with a different immediate cause. One access-policy synchronization defect recorded as repaired in the first round was still blocking new worker sign-ins in the second: the first entry had already noted that stored data was not migrated, and the repair did not reach it. Storage gaps turned up the same way: three record types broke one at a time, then a single sweep listed 11 more with no home in the new database. We then had agents count whole classes with a syntax-aware code-search and census tool we built. It found 708 direct legacy data calls in 155 files, 995 path-related candidate sites, 901 test files that are candidates for testing against a fake of the platform API, and permission definitions in at least six separately maintained places. Counting was the easy part. A guarded rewrite tool changed 4 of the 777 data calls automatically and left 385 for reviewed manual changes, 207 of them because the module those calls should move into did not exist yet. Data from October 21 to 22, 2026, analyzed October 23, 2026. This is a tentative case study of one codebase during one migration. We did not measure whether census-first triage reduced repeat fixes afterwards.

One flow, repeated breaks

5 in 2 rounds

Related entries on new worker account creation and first sign-in, each with a different immediate cause

Records with no database home

3 singly, 11 in one sweep

Three surfaced one at a time as bugs; one inventory sweep then listed 11 more record types

Legacy data calls counted

708 in 155 files

Syntax-aware census, plus 69 calls through older wrappers in 27 files

Rewritten automatically

4 of 777 calls

385 left for reviewed manual change; 388 held by other running lanes

Empirical Findings Table

One flow appeared in five related bug entries across two rounds of one-at-a-time fixes. A census then sized whole classes syntactically in one pass, and the guarded rewrite changed 4 of the 777 data calls it counted.
Telemetry MetricMeasured ValueContext & Observability
Related worker flow entries5 in 2 roundsAn access-policy synchronization defect, a role repair that wrote to a different store than it read, user profiles with no table, the same policy defect still present in stored data a round later, and an access-policy gap on first sign-in.
Storage-home bugs3 singly, 11 in one sweepThe bug log names this the biggest repeat and gives the root cause as no single inventory of the paths the app reads and writes.
Failing check rows to root causes227 rows, 22 causes15 application or configuration causes, 4 problems in the check script itself and 3 fixture or product-decision items. One cause, a database configuration gap, accounted for 60 of the 227 rows.
Direct legacy data calls708 in 155 filesPlus 69 calls through older wrapper functions in 27 files, for 777 calls in all.
Path-related candidate sites995 sites in 235 filesSyntactic matches for path construction, path helpers and validators, and path literals outside the modules meant to own storage locations. Candidates, not confirmed hand-built paths.
Fake-API test candidates901 filesTest files that use or implement a fake of the platform API. Candidates, not confirmed fakes: some are real-path adapters sharing the same interface.
Places permissions are defined or decidedAt least 6Two in the platform core, three in the application server and one in the web app, from one inventory; the count does not establish six independent authorities. The application server alone had 615 direct permission-check sites in 109 files; the web app had 218 direct permission calls in 94 files.
Automatic rewrites4 of 777 calls385 manual and 388 skipped. A final whole-repository dry run proposed no further automatic rewrites under the tool's guards; 4 is the subset the tool accepted, not a measured maximum. The committed baseline for direct calls fell from 708 to 704.

Engineering Action Directives

DO

When an AI agent reports a bug fixed, ask for the count of other sites with the same flaw, produced by a tool, before accepting the fix.

DON'T

Accept "fixed" for a flaw that could exist elsewhere without a number for how many other places were checked.

DO

Keep a count baseline for each known bad pattern and fail any change that raises it.

DON'T

Expect an automatic rewrite to clear the class on its own. Here 207 of the 385 manual cases, 27% of the 773 calls not rewritten, needed a destination that did not exist yet.

Methodology Boundaries & Limits

  • **One codebase, one migration, two days.** These are observations from a single cutover with small counts. They do not estimate how often one-at-a-time fixing repeats across projects, teams or model families.
  • **No before-and-after measurement.** The triage protocol and census arrived mid-stream. We did not measure whether repeat fixes fell afterwards, or time an agent finding all sites with the tool against plain text search on the same bugs.
  • **The counts depend on our grouping.** "Five worker flow entries" and "at least six places" follow the counting rules above; a different grouping could give a different count, or more places if overrides and cached copies are counted separately.
  • **Census counts are syntactic.** They follow how code is written, so dynamic calls and aliases can be missed or miscounted, a census list cannot certify that it is complete, the 995 path-related sites are candidates rather than confirmed hand-built paths, and the 901 fake-API test files are candidates rather than confirmed problems.
  • **Model identities are not recorded per entry.** The log does not establish which model wrote each fix, so no model comparison follows.