# Your agent treats every TODO like it's blocking. Mark which ones aren't.

You leave a comment in the middle of a refactor:

```js
// TODO: cache this call for the list endpoint
```

You meant: come back to this when the list page actually feels slow. Two days later the agent opens a branch and the diff has 400 lines: a new `CacheService`, a TTL config, invalidation hooks for three other endpoints, and unit tests for the edge case where the cache warms during a deploy.

You didn't ask for any of that. You wrote a note to yourself.

## TODOs are not task tickets

Humans read `// TODO:` with a lifetime of context. We know which comments are from last sprint's cleanup pass, which ones are jokes, and which ones actually block a release. An agent reading the same file sees a flat list of open instructions. Every TODO looks equally actionable because it is, syntactically, an instruction.

The training signal is stacked against you. Code on GitHub is full of TODOs that grew into features, TODOs that were fixed in a later commit, and TODOs that an engineer meant to address next week. The pattern the agent learns is: TODOs get implemented. It doesn't learn the meta-rule that half of them should be ignored.

## What gets built

The most common over-build is around error handling. A TODO like `// TODO: handle null case` becomes a 20-line guard block with a custom error type, a log line, and a retry wrapper. The null case happens once a month and the original author would have been fine with `if (!x) return;`.

The second most common is around config. `// TODO: make this a setting` becomes a new env var, a settings UI field, and a migration for the default value. You meant: hardcode it for now and revisit if a second deployment needs a different number.

Both of these are defensible code. That's the problem. The code isn't wrong, it's just more than you asked for, and every line of it is now something you have to review, test, and maintain.

## The fix is a prefix, not a prompt

You can try to tell the agent in the system prompt "don't implement TODOs unless I ask." It works for about two sessions. Then a new model version resets the behavior, or the agent hits a context window edge and forgets the instruction.

The fix that stuck for us is mechanical: prefix every TODO with an explicit lifetime.

```js
// TODO(later): cache this call. List page feels fine.
// TODO(now): null check crashes on the export path.
// TODO(never): this is a known limitation of the mock server.
```

Then the rule is one line: only touch `TODO(now)` comments. `TODO(later)` is a note for humans. `TODO(never)` is a documented tradeoff, not a bug.

This works because it doesn't rely on the agent remembering a preference. It's in the file, it's greppable, and it survives model switches. You can even lint it: fail the build if an agent PR adds a TODO without a prefix.

## What this has to do with specs

The underlying issue is the same one that shows up in API work: the agent treats a note as a contract. When a human leaves a TODO, they're writing to themselves. When an agent reads it, it reads to a spec. The gap between "a thing I might do later" and "a thing you should build now" is exactly the gap that explicit markers close.

We ran into the same pattern when agents started generating OpenAPI specs from code. The agent saw a comment on an endpoint like `// TODO: add pagination` and turned it into a full query parameter, a response envelope change, and a test. The endpoint didn't need pagination. The comment was from 2023.

We ended up treating TODOs the way we treat spec comments: if it matters, it's marked. If it's not marked, it's not a requirement. The local-first flow in [Powerduck](https://www.powerduck.com/) is built around that principle — the spec file is the source of truth, and a stray comment in the codebase is not.

## The cheap version

You don't need a whole toolchain. Before you hand an agent a task, grep the target directory for `TODO` and look at what's there. If the list is longer than five items, you have a problem: the agent will find all of them and try to fix all of them.

Either clean up the old TODOs first, or add the prefixes in a five-minute pass. It's faster than reviewing 400 lines of cache infrastructure you didn't want.

