Addaly is in open beta. Things will change, and AI answers can be wrong — check anything that matters.

Pairing with a model on real work

How Software Development Changed · lesson 6 of 8 · 10 min

A real task, not a demo

Demos use empty directories. Here is something closer to your week.

You have a billing service, four years old, about 40,000 lines. Invoice totals are computed in one place and assume a single currency. Finance now wants line items in the currency they were charged in, with the invoice total in the account's base currency, using the rate at the time of each charge.

This is normal work: an existing system, real constraints, and consequences if you get it wrong.

Start by making it read, not write

The first request should produce no code.

Read billing/invoice.py, billing/line_item.py, billing/fx.py, and the migration in migrations/0142_*.sql. Describe how an invoice total is computed today, where currency is assumed, and every place that assumption is baked in. Do not write code.

Read the answer carefully. You are not checking whether it is impressive, you are checking whether it matches what you know. If it has invented a helper that does not exist, or missed the second code path, you have found that out for the cost of one prompt instead of one diff.

This step catches the most expensive failure — a confident change built on a wrong mental model — before it exists.

Work in steps you can run

The unit of work is: one small change, run something, commit or throw away.

Not "implement multi-currency invoicing." Instead:

  1. 1Add a currency column and backfill it with the existing default. Run the migration on a copy. Commit.
  2. 2Add a pure convert(amount, from_ccy, to_ccy, at) function with your own tests. Commit.
  3. 3Change one call site. Run the test suite. Commit.
  4. 4Change the rest.

Each step has a checkpoint you can actually execute. The reason is not tidiness. It is that you want the cost of being wrong to stay at fifteen minutes, and small commits are what keeps it there.

Say what not to do

Constraints are more useful than instructions, and they are usually the part people leave out:

Do not add a dependency. Do not change the public signature of Invoice.total(). Do not touch the migrations directory. If you think the schema needs to change, say so and stop.

"Say so and stop" is worth having in your vocabulary. Without it, uncertainty gets resolved by guessing, and the guess arrives dressed as a decision.

Give it the real text

Paste the actual stack trace, the actual failing test output, the actual file. Not your summary of them.

FAILED tests/test_invoice.py::test_total_with_mixed_currency
E  decimal.InvalidOperation: [<class 'decimal.DivisionUndefined'>]
E  billing/fx.py:88: in convert
E      return (amount / rate).quantize(TWO_PLACES)

Your paraphrase drops the line number, the exception subclass, and the expression — which is where the answer usually is. This sounds obvious and it is one of the most common avoidable mistakes.

Know when to restart instead of arguing

If it is wrong twice in the same way, stop correcting it. A conversation that has gone off is difficult to steer back, because everything already said is still shaping what comes next. Start again with better framing: the constraint you discovered, the file you forgot to include, the thing you now know it misunderstood.

Debugging the conversation almost always costs more than restarting it. People spend twenty minutes on the third correction because the first two felt so close.

The refusals worth practising

Never accept a fix that changes the test to match the code. When a test fails and the proposed fix edits the assertion, that is the failure mode to watch for. Sometimes the test really was wrong. Decide that yourself, out loud, with a reason.

Do not hand over architecture on a system you will maintain for four years. Which of two designs to adopt is a bet on what changes next, and that is a judgement about your business.

Do not accept a change you do not understand, even when it works. This is the discipline that holds the whole thing up. If you would not have written it and you cannot say why it is right, you are not finished — you have just moved the work to whoever gets paged.

About the agentic modes

The tools that run commands and edit many files unattended are where both the leverage and the risk sit. They can also drop tables, force-push, and install things. Treat them the way you would treat a script with your credentials: sandboxed, permissioned, and with the diff read before it lands.

The specific tools here change every few months, and anything written about them in 2026 will look quaint in 2028. The discipline underneath does not change: small reversible steps, a checkpoint you can run, and a human who can explain the result.

Before you move on

A test has failed twice. Both times you explained the failure and got back a change that did not fix it. You are now composing a third, more detailed correction. What is usually the better move?

Pick the one you would defend. Nobody sees your answer.

No ads. No data sale. No public scores on people. Ever.

© 2026 Addaly