# Your Agent Renamed the Function — It Just Missed the Caller That Referenced It by String

## The rename that looks safe

You ask the agent to rename `process_payment` to `settle_payment`. It runs across the codebase, updates every import, renames the definition, updates the docstring, and opens a tidy PR. The diff is 14 files, every hunk is a clean rename, the linter passes, the unit tests pass.

Nothing in CI flags a problem. Two days later, a scheduled job that runs every hour silently stops doing anything. The cron entry still says `handler = 'jobs.process_payment'`. The dispatcher looks up the string by name, finds nothing, and swallows the lookup error.

## Why the static rename misses this

A rename tool rewrites identifiers it can resolve as symbols. References that live inside strings are not symbols from its point of view. They are data.

The list of places a function name can survive as a string is longer than people think:

- Cron job configs and task runners that resolve handlers by dotted path
- Route tables that map URL paths to view names
- DI containers and service locators that look up factories by name
- Feature-flag configs that reference callback names
- Dynamic dispatch in event handlers or plugin systems
- Test names in a separate e2e suite that the agent does not see
- Documentation strings and error messages that print the old name (cosmetic, but confusing)

The agent's grep for `process_payment` will catch the import lines. It will not catch the string in `cron.yaml`, because that file is either outside the directory it was pointed at, or it is YAML and the rename tool treats it as opaque data.

## The cheap guard that catches it

Before the agent calls a rename done, ask it to do one extra thing:

> After renaming, grep the whole repo (including yaml, json, toml, and any config directory) for the old name as a string literal. List every hit and say whether it needs to be updated, kept for backward compatibility, or removed.

That one prompt step catches the cron entry, the route table, and the DI registration. It also catches the case where the old name is intentionally kept as a public alias — in which case the agent should say so explicitly, not silently drop it.

A second, even cheaper check: run the application's startup path after the rename. Most dispatcher and route registration errors surface as "module not found" or "handler not registered" the moment the app boots, long before the cron job fires. If the agent can run `npm start` (or the equivalent) and paste the boot log, the missing reference shows up in five seconds.

## What to look for in review

When a rename PR crosses your desk, the question is not "did every import update?" It is:

- Does the agent's grep include config files and strings, not just code?
- Did the application boot after the rename?
- Is there a public alias that needs to stay for existing callers?

A rename that only touches `.py` or `.ts` files and shows no boot log is not verified. It has just been statically rewritten. The runtime references are exactly the ones static analysis cannot see.

## The same gap shows up in API renames

Agents do the same thing when they rename an API field or a route path: they update the controller, the request type, and the OpenAPI snippet in the README. They do not check that the production client (a mobile app, a browser extension, a third-party integration) still sends the old name.

The local guard we landed on in [Powerduck](https://www.powerduck.com/) is to re-run the spec against the live endpoint after the rename — the old client payload that still works in production either breaks the check (good, you find out before release) or confirms the alias is still accepted (good, you know you kept backward compatibility on purpose). Either way, the string reference that lived outside the codebase stops being a review-time surprise.

## What to change tomorrow

Next time your agent opens a rename PR, ask for the boot log and the string-grep hits before you hit approve. The rename itself is probably correct. The thing that breaks at runtime is the reference nobody told the agent to look for.
