"Finish the portal's home page" - a request like that hides several different jobs at once. The promotions list is missing a filter. The banner button links to the wrong place. The leaderboard's data preparation is written twice, so every change to it costs double. And nobody quite remembers where the promotion's address comes from in the first place.

A person given that request would most likely ask a follow-up question. Claude Code can ask too, but it often fills the gaps on its own - with plausible work nobody asked for. And each type of task gets its own kind of extra work: the filter comes with a search box, the link fix with a new look, the refactoring "fixes" the sorting along the way, and the research ends in edits.

What should change

Roughly speaking, you tell the types apart by what's different once the work is done:

  • there's behavior that didn't exist before - a feature, a new capability;
  • the behavior now matches what was expected - a bugfix, fixing a bug. This also covers something that's already built but never worked as agreed;
  • from the outside everything is the same, but the code inside is organized differently - refactoring;
  • you got an answer to a question about the project, and the source files haven't changed - research.

The type tells you what to pin down in the request and what to check. How much freedom to give the agent also depends on the cost of a mistake and the size of the task: a change in code that people actually use deserves more attention than a new page in a practice project. There are mixed tasks too, research followed by an edit, for example. Then each stage has its own result and its own boundary.

A new feature

The promotions list needs a toggle that shows only the active ones. Let's set the conditions right away: a promotion counts as active if it has the flag active: true; promotions A and C have it on, B has it off. The data here is made up for the example, and the requests below are templates you can carry over to your own project.

The agent will most likely handle "Add a filter for active promotions", and then some. You get the toggle, a search box next to it "since we're filtering anyway", and sorting by end date on top. Each addition makes sense on its own. Together they turn one feature into a small subsystem that nobody ordered and that now also has to be checked.

At least you can see the extras on the page. It's worse when the agent quietly makes a decision you never made. Andrej Karpathy told a story about his project MenuGen: sign-in went through Google, payments through Stripe, and the agent linked purchases to accounts by email. Anyone whose email differs between the two services pays, and the payment never reaches their account. Decisions about data - which field links records together and what to do with the records already in the project - are yours to make, and preferably right in the request. Ours is a simpler question: what to do with a promotion that has no active flag at all.

Another source of improvisation is the pattern the agent copies. It looks for similar code in the project and repeats it, and the similar code may turn out to be exactly the spot everyone has wanted to rewrite for ages (every project has one). If the project has a good example, point to it yourself.

A new feature needs one user scenario and an explicit list of what's not part of the task:

Add an "Active only" toggle to the promotions list on the home page.
An active promotion is a record with active: true; a record without this field is inactive.
Check on the current data: on - A and C are shown, off - A, B and C.
Don't add search, sorting or other filters, those are separate tasks.
If the project already has a similar toggle, follow it
and tell me which one you based it on.
First describe the scenario you're going to build in one sentence
and wait for my reply. Don't change any files yet.

The last two lines cost little but pay off: if the agent's summary of the scenario doesn't match what you had in mind, you see it before any edits. When the agent shows you its plan, ask it a short question: is the solution overcomplicated, is anything left unfinished, and why does it think so. That question works for any plan, but especially for a feature, because this is exactly where the extras hide. Once it's done, check both states of the toggle, and while you're at it, see whether anything extra showed up on the page.

Fixing a bug

The banner button on the home page should open the /campaign/ page with the promotion's terms, but it leads to /old/.

The shortest path for the agent is to write /campaign/ straight into the button's link. If the address really was written in the link, that's enough. But if it comes from shared data that other buttons use too, the substitution will mask the symptom: this button will work, and the error in the data will stay. And the second typical move - tidying up the banner's spacing and color, since the file's open anyway.

Address in shared data: a fix in the button repairs only the banner, the other button still leads to /old/; a fix in the data corrects the address for both buttonsFix in the buttonFix in the datadata/promo.jsonurl: /old/Banner/campaign/Other button/old/data/promo.jsonurl: /campaign/Banner/campaign/Other button/campaign/
Where to fix it depends on where the button gets its address

The button itself won't tell you which case you're dealing with; only the code will.

Before asking for anything, reproduce the failure yourself: click the button and see where it goes. If the bug doesn't reproduce for you, don't rush to close the task; first pin down the steps and the data it was seen with. Once the failure is reproduced, you need the cause. Don't know where the button gets its address? That's fine: that's exactly the first question for the agent:

The banner button on the home page leads to /old/, it should lead to /campaign/.
First find where the button gets its address and show me that place.
Don't change any files yet.
Once I confirm, fix the address where it's defined.
Don't touch the banner's styling.

After the fix, repeat the original action: click the button, check the address, make sure the page shows the promotion's terms. If the shared address data changed, check one more place that uses it.

Changing how the code is organized

The leaderboard's data preparation is written twice, almost identically, and every change has to be made in both places. The task is to keep one version and leave the table unchanged.

What has to stay the same through the change is called an invariant. Here it's the order of participants and the numbers in the table, given the same data.

When a refactoring breaks something, it breaks quietly. Tied scores get sorted differently, the rounding changes, and there are no error messages; the table just shows the wrong thing. And the agent, having merged the two versions, may well report "behavior unchanged" without running anything. Or "improve" the sorting along the way because the old one looked odd to it.

Take a data set in this order: A with 10 points, C with 20, B with 20, D with 15.5. Today the table shows C: 20, B: 20, D: 15.5, A: 10. The baseline for the refactoring is exactly this output of the current code, even if you'd prefer something else. The set was put together deliberately. C comes before B, so if the new version starts ordering tied scores by name, B jumps ahead. And the fractional value shows it if the rounding drifts.

Before the refactoring the data set goes through two copies of the preparation, after it through one version; the input and the resulting table C 20, B 20, D 15.5, A 10 are the sameBeforeAfter=Same input and table, only the middle changedData set A, B, C, DData set A, B, C, DCopy 1Copy 2Preparationone versionTableC 20, B 20, D 15.5, A 10TableC 20, B 20, D 15.5, A 10
The invariant is what sits at the edges of the diagram

Here's a request that covers both failure modes:

The leaderboard's data preparation is repeated in two places, keep one.
Don't change the table's behavior, even if something in it looks odd;
list those spots separately.
Before the change, run the existing checks and print the table
for the data set A: 10, C: 20, B: 20, D: 15.5. Save both outputs.
After the change, do the same again and compare.
In the report, show where the data preparation lives now.

Compare the saved outputs yourself instead of relying only on the "matches" line in the report. A match tells you the behavior held on this data. That's all it tells you. The last line of the request checks the task itself: an identical table doesn't yet mean the duplication is really gone.

And here a half-measure is worse than nothing. Say one copy stayed and some of the calls moved to the new version. The table is the same, but now there are two ways to prepare the data, and the agent may well handle your next request on top of the old one: it has no way of knowing which one is the right one. Once you've started merging, take it all the way to one version, and if you're running out of time, stop earlier and write down where things were left.

Research without fixes

Research is the most different of the four: what you get at the end isn't a changed project but an answer. The question from our portal is where in the code the promotion button's address gets chosen. It's the same question the bug fix started with, only here nobody has asked for a fix at all. That's what a mixed task looks like: research first, then the fix as a separate stage.

The agent has two typical failure modes here. The first is starting to fix things along the way: it finds a clumsy piece of code, and fixing it seems cheaper than describing it. That turns research into an edit with no spec and no check. The second is subtler. The agent has read the code and confidently explains how the page works, although it never ran it, and from the outside a summary of what it read looks just like an observation.

The third failure starts with the request itself. Mention in it what you plan to do next, and the agent will bend the answer toward that goal: instead of how things work now, you get an opinion on how they should work. So in research, ask how things are built right now. Your plans can wait for the next stage. The request below doesn't say a word about fixing the address later.

Find where the banner button on the home page gets its address. Don't fix anything.
In your answer: the files and places in the code, how they're connected,
what you established by reading and what by running,
and what you don't know yet.

A good answer to that request looks roughly like this: "In pages/home.html the button's address comes from promo.url; the value /old/ is set in data/promo.json. I established this by reading the two files. I didn't run the page and didn't check whether any scripts change the address." The connection can be checked, and the limit of what's known is stated honestly.

If something suspicious turned up along the way, let it go into the answer as a separate line: what's visible and what's missing to draw a conclusion. the fix is the next stage, with its own spec.

Plan mode for research

Plan mode is handy for research: source files aren't edited in it (unless bypassPermissions is available in your terminal session, in which case nothing is blocked, even if you never switched to that mode). Read-only commands run without asking; others will ask for permission or go through an automatic check, so keep an eye on what gets run anyway. You don't need to approve the plan at the end: approving it will start the edits. Take the answer and leave plan mode with Shift+Tab, pressing it until manual mode on appears in the status bar. If you have access to auto mode, it may come right after plan mode in that cycle.

First step and boundaries

Here it all is in one table.

TypeFirst questionWhat the agent will do on its ownWhat to check
FeatureWhat new action does the user need?add nearby conveniences, make data decisions on its ownthe specified scenario works, nothing extra
BugfixWhat happens instead of what's expected?patch the symptom or restyle something nearbythe original scenario gives the right result
RefactoringWhat must stay the same?report without running anything, "improve" the behavior, or quit halfwaythe before and after outputs match, the duplication is fully gone
ResearchHow does it work right now?start editing, or pass off reading as observationan answer with files, evidence, and unknowns

The third column is what's worth ruling out explicitly in the request. The fourth is for checking, either yourself or by asking the agent to show it in its answer.

And the flip side: the name of the type doesn't permit anything by itself. "It's just a refactoring" is no reason to rewrite half a module, and "it's a bugfix" isn't a license to change the styling while you're at it. The type suggests the question and the check; the boundaries are still yours to set.

Rewrite six requests

Below are six requests the way people usually write them. For each one, name the type and rewrite the request so the agent has less to guess: the result, the boundary, the check. The walkthrough comes right after, so try it yourself first.

  1. "Add a CSV export for the leaderboard."
  2. "The leaderboard sometimes shows the same participant twice, fix it."
  3. "Split pages/home.html into parts, it's huge."
  4. "Why does the home page load so slowly?"
  5. "Fix the link and redo the styling while you're at it."
  6. "Make the portal better."

Here's one possible walkthrough. Your wording may differ; what matters is that it rests on the same anchors.

1. Leaderboard export.
Feature. The scenario is missing: which columns go into the file, what order the rows are in, where the export button is. There's also a data question that's easy to miss: do participants who don't have any points yet go into the file? Decide that yourself, or the agent will. And on a separate line, what not to do: import, column selection, other formats. The check is simple: export the file using the data set A, B, C, D and compare the rows with the table on screen.

2. A participant shown twice.
Bugfix, but the key word here is "sometimes", not "fix it". As long as nobody knows when the duplicate appears, the agent has nothing to fix, and its most likely move is to strip out repeats before showing the table. That's the masked symptom right there. First find out after which action and with what data the row doubles, then ask the agent to find the place where it happens, without edits. And you check it with the same scenario that produced the duplicate.

3. Splitting a big file.
Refactoring, except the invariant isn't named, so there's nothing to check "nothing broke" against. Add it: the page looks and works as before - banner, promotions list, leaderboard; and before the change, record what the checks show. And rule out the temptation: while spreading the markup across files, the agent can easily adjust spacing or rename classes along the way.

4. A slow page.
Research: it's a question, not an order to speed things up. But the agent can easily read it as "make it faster", and without "don't change anything" the answer turns into optimization by guesswork. Ask for the answer to separate what was measured from what was read: "the images weigh several megabytes" is a fact if the agent checked it, while "a script is probably slowing things down" is a guess. The fix comes as the next stage, once the cause is known.

5. Fix the link and redo the styling.
Two results in one request. Fixing the link is a bugfix. The new styling doesn't honestly fit any of the four types: the behavior doesn't change, the look does. It's closest to a feature, except the result is defined not by a scenario but by a reference - a mockup or a screenshot. The fix goes first, with the request from the bugfix section, and once it's checked, the styling:

Now restyle the banner to match the mockup @banner-mockup.png.
Don't change the button's address or the texts.

6. Make the portal better.
There's no way to tell the type, and no need to guess. The request turns into a question for whoever asked: what exactly is getting in the way right now? If the request was yours, then ask yourself. You can also hand this to the agent:

Before changing anything, ask me up to five questions
you need answered to understand what exactly to improve.
Don't change any files.

The type usually becomes clear from the answers on its own.