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.
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 Metric | Measured Value | Context & Observability |
|---|---|---|
| Related worker flow entries | 5 in 2 rounds | An 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 bugs | 3 singly, 11 in one sweep | The 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 causes | 227 rows, 22 causes | 15 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 calls | 708 in 155 files | Plus 69 calls through older wrapper functions in 27 files, for 777 calls in all. |
| Path-related candidate sites | 995 sites in 235 files | Syntactic 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 candidates | 901 files | Test 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 decided | At least 6 | Two 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 rewrites | 4 of 777 calls | 385 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
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.
Accept "fixed" for a flaw that could exist elsewhere without a number for how many other places were checked.
Keep a count baseline for each known bad pattern and fail any change that raises it.
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.