Supply relevant context
- Lesson 5
- 40 min
- Module 2: Write actionable tasks
Lesson 5 of 15 · AI-Assisted Software DevelopmentSupply relevant context
1. Establish a safe working setup
2. Write actionable tasks
3. Review generated work
4. Debug and test with assistance
5. Deliver maintainable work
What you will be able to do
Give an assistant what a new colleague would need for this one task. That is the exact observation, the expected result, a small example, and the files and names that matter. Leave out everything else, and never include a secret.
Before you startWhat to know and to have ready
What you need to know
- Task briefs and acceptance criteria, from Problem and acceptance criteria.
- The repository map and what an agent sends to the model, from Assistant interaction modes.
- How
ticket-cleanercleans a row (parsing.py) and counts it (report.py), from Structured records in the Python course.
What you need on your computer
- The project
~/projects/ticket-cleaner-assistwith the brief of the last lesson committed, and its environment active.python -m pytestprints25 passed, andgit statussaysworking tree clean. - If the project is missing or broken, use the reset steps of Context and boundaries, then do Add the brief to your project again.
Phoning the garage
Section titled “Phoning the garage”Your car makes a strange noise, so you phone the garage. “My car makes a noise. Can you fix it?” The mechanic can only ask questions back: what kind of noise, when, from where?
Compare: “A high squeak from the front left wheel when I brake. It started on Tuesday, and it stops after ten minutes of driving. I recorded it: here is a ten-second video.” Now the mechanic knows what to look at first, and how to check the repair.
You did not send the car’s full service history, your insurance papers or the key to your house. The mechanic does not need them for this noise, and some of them are private.
The problem: the assistant sees the wrong part
Section titled “The problem: the assistant sees the wrong part”The course team gave the assistant Grace’s bug with very little: one file, ticket_cleaner/report.py, no repository map, and one sentence (transcript bug-little-context):
The categories in the report are wrong. Fix it.The assistant changed nothing. It answered with a question:
Could you share a sample of the incorrect category counts and the expected result? Currently, the report counts categories only for tickets matching therequested status, and treats category names with different capitalization or whitespace as distinct. Which behavior should change?This time, the assistant asked instead of guessing. That is good, but do not count on it: another run, or another model, can guess. And look at what it could see. report.py counts the categories that it receives. The bug is not there. The cause is in parsing.py, which the assistant never saw. It even guessed wrong about spaces: the program already removes them, in a file that it could not read.
So the session cost 2,220 tokens and changed nothing. The request had no observation, no expected result and no example. The one file that it had was the place where the bug shows, not the place where it is.
The idea: relevant context
Section titled “The idea: relevant context”The context of a request is everything that the model receives with it. That is your prompt, the files, the repository map, and the earlier turns of the conversation. The model works only from its context. It knows nothing else about your project.
Relevant context is the part that this task needs. For a bug or a change, it has five kinds of information:
- The observation: the command that you ran, and its exact output or error message, pasted, not retold.
- The expected result: what the output should be.
- A minimal example: the smallest input that still shows the problem.
- File references: where the code is, by path.
- Interfaces: the names and signatures that the change must keep, such as
clean_category(value: object) -> str.
Leave out what the task does not need: other files, the whole data file, logs from last month. And never include a secret, such as the token in .env, or real customers’ personal data. More text is not better context. It costs tokens, it gives the model more places to look, and every pasted line leaves your computer.
A tiny example: from twelve rows to two
Section titled “A tiny example: from twelve rows to two”Grace’s export has 12 rows. Which of them show the bug? Look only at one team, login. The export has four login tickets, written in four ways: login, Sign-in, Login and LOGIN. Sign-in is a web form name, so it already becomes login. That leaves capital letters as the only difference.
So two rows are enough: one login and one LOGIN, both open.
id,status,category,priority,subjectT-1,open,login,1,OneT-2,open,LOGIN,1,TwoExpected: {"login": 2}, because both tickets belong to the login team. If the program gives {"LOGIN": 1, "login": 1}, the bug is there, in two rows that anyone can read in five seconds. A minimal example is this: the smallest input that still fails. Reproduce first shows how to make one step by step.
Find where the bug is
Section titled “Find where the bug is”Grace sees the bug in the report. But where does a category get its text? The diagram follows one row through the program:
Text description of the diagram
The diagram follows one row with the category LOGIN through the program, in five steps. First, the data file has the row. Second, read_rows() in files.py reads the row as text: “LOGIN”. Third, clean_category() in parsing.py, in red, looks the name up among the web form’s names, in small letters. “login” is not a web form name, so the function returns the original text, “LOGIN”. The diagram marks this step: the cause is here. Fourth, count_by_category() in report.py counts the text as it is: {"LOGIN": 1, "login": 1}. Fifth, reports/summary.json shows two lines for one team. Steps four and five are marked: you see the symptom here. A dashed note under report.py says that it was the only file in the too-little-context session. A dashed note under the middle steps lists the files of the relevant-context session. They are parsing.py, records.py with the web form’s names, and tests/test_parsing.py.
You do not have to guess the files. Search the code for the word category:
grep -n category ticket_cleaner/*.pySelect-String -Pattern category -Path ticket_cleaner\*.pyticket_cleaner/parsing.py:18:def clean_category(value: object) -> str:ticket_cleaner/parsing.py:19: """Return the category, with the web form's names changed to the report's names."""ticket_cleaner/parsing.py:48: category=clean_category(raw["category"]),ticket_cleaner/records.py:5:REQUIRED_FIELDS = ("id", "status", "category", "priority")ticket_cleaner/records.py:21: category: strticket_cleaner/report.py:9:def count_by_category(tickets: list[Ticket]) -> dict[str, int]:ticket_cleaner/report.py:10: """Return the number of tickets in each category, sorted by category."""ticket_cleaner/report.py:13: counts[ticket.category] = counts.get(ticket.category, 0) + 1ticket_cleaner/report.py:31: "by_category": count_by_category(selected),Three files mention categories. report.py only counts. records.py has the field, and also the web form’s names, CATEGORY_ALIASES, a few lines below line 5. parsing.py has the function that makes the text: clean_category(), called on line 48. That is where to look first, and the file references of the bug report.
Write the bug report
Section titled “Write the bug report”Amira writes the five kinds of context into a short bug report. You make the minimal input, see the bug yourself, and add the report to the project.
-
Run the program on Grace’s export, and open the report:
Terminal window python -m ticket_cleaner data/web-form-export.csvOutput 12 rows: 12 valid, 0 rejected.Report: reports/summary.jsonIn
reports/summary.json,by_categoryhas seven lines:reports/summary.json (part) "by_category": {"Billing": 1,"LOGIN": 1,"Login": 1,"account": 1,"billing": 2,"login": 2,"shipping": 2}, -
In your editor, make a new file
minimal.csvin the project folder, with the three lines of the tiny example above. -
Run the program on it. Write the report to a new file, so that the export’s report stays:
Terminal window python -m ticket_cleaner minimal.csv --output reports/minimal.jsonOutput 2 rows: 2 valid, 0 rejected.Report: reports/minimal.jsonreports/minimal.jsonhas"by_category": {"LOGIN": 1, "login": 1}, on four lines. Both rows are valid, so the program prints no warning: nothing tells Grace that something is wrong. -
Copy the bug report from the snapshot
end-of-m02:Terminal window cp ../nextia-learning-labs/C15/snapshots/end-of-m02/docs/tasks/category-names-bug.md docs/tasks/Terminal window Copy-Item ..\nextia-learning-labs\C15\snapshots\end-of-m02\docs\tasks\category-names-bug.md docs\tasks\ -
Delete
minimal.csv. The bug report has its three lines, so anyone can make it again. On Windows, useRemove-Item minimal.csv.Terminal window rm minimal.csv -
Check and commit:
Terminal window ruff format --check .git add docs/tasks/category-names-bug.mdgit commit -m "Write Grace's bug report with a minimal input"Output 19 files already formatted[feature/category-option de7db2e] Write Grace's bug report with a minimal input1 file changed, 48 insertions(+)create mode 100644 docs/tasks/category-names-bug.md
Here is the report. Find the five kinds of context in it:
# Bug: one team appears under several category names
Reported by: Grace (support lead), with this week's export from the new webform (`data/web-form-export.csv`).
## Steps to reproduce
1. Make a file `minimal.csv` with two tickets of the same team:
```text id,status,category,priority,subject T-1,open,login,1,One T-2,open,LOGIN,1,Two ```
2. Run `python -m ticket_cleaner minimal.csv --output reports/minimal.json`.
## Observed
`"by_category": {"LOGIN": 1, "login": 1}`: two lines for one team.
With Grace's export, the report has `Billing`, `LOGIN` and `Login` next to`billing` and `login`.
## Expected
`"by_category": {"login": 2}`. Capital letters and spaces around a category donot make a new category, as for the status and the ID. With Grace's export:account 1, billing 3, login 4, shipping 2.
## Not affected
The web form's other names (`Sign-in`, `Invoice`, `Delivery`) are alreadycounted under the report's names.
## Environment
The same result in a new virtual environment made from`requirements-lock.txt` (Python 3.14), and in Grace's own environment: not anenvironment problem. The rows are valid, so no warning is printed.
## Evidence of done
- A regression test with the two rows above fails on the current code and passes after the fix.- Grace's export gives one line per team.- All other tests and the sample file's report (`tests/test_baseline.py`) are unchanged.The observation and the expected result are exact. The example is two rows. “Not affected” and “Environment” save the reader two wrong paths. The report has no file references: Grace is not a developer. Amira adds them in the prompt, from the search above. The report also says nothing about how to fix the bug. That is the fixer’s job.
The same bug, with relevant context
Section titled “The same bug, with relevant context”A second session got more (transcript bug-relevant-context). It had Grace’s email, the two rows with the observed and expected result, three files and the repository map. The prompt ended with the file references and a constraint:
The categories are cleaned in ticket_cleaner/parsing.py (clean_category, to_ticket); the web form's names are in ticket_cleaner/records.py (CATEGORY_ALIASES). Fix the cause, add a regression test to tests/test_parsing.py, and change nothing else.The assistant named the cause in its first sentence. Then it rewrote the three lines of clean_category() and added a test:
`clean_category()` lowercases alias lookups but preserves case for other categories. Use `clean_text()` before resolving aliases so every category isnormalized.Text description of the diagram
The diagram compares two recorded sessions with the same model. The left column is the session with too little context. Its prompt was “The categories in the report are wrong. Fix it.” It had one file, ticket_cleaner/report.py, no repository map and no example input. It changed nothing: the assistant asked for a sample of the incorrect category counts and the expected result. It used 2,220 tokens in, in one model call. The right column is the session with relevant context. Its prompt had Grace’s email with the exact output, the two-row input, and the observed and the expected result. It ended with the request “Fix the cause, add a regression test, and change nothing else.” It had three files, parsing.py, records.py and tests/test_parsing.py, and the repository map. It changed 2 files, 20 lines added and 3 removed. The tests gave 31 passed, and all 5 bug checks passed. It used 4,570 tokens in, in one model call.
The session changed 2 files (+20 −3), and all 5 hidden checks of the bug passed. Of its 7 new test cases, 6 fail on the unfixed code. One, login → login, passes on both versions, so it catches nothing.
Do not apply this fix now. The session ran in a throwaway copy, and it is a good result. But nobody saw a test fail before the fix, so nobody showed that its test catches the bug. Your project keeps the bug until Module 4, where you fix it with that evidence. The next task is still Grace’s feature.
When to add context, and what it costs
Section titled “When to add context, and what it costs”Context costs tokens. The session with little context used 2,220 tokens in and cost US$0.0049. The one with relevant context used 4,570 and cost US$0.0126. That is about twice the tokens and two and a half times the cost, and the cheaper session produced nothing. Prices change: check your provider’s current page. With a free tier or no assistant, you pay nothing.
The larger cost is your time: about ten minutes to make the minimal input and find the files. You spend that time anyway, when you check the fix.
Too much context also costs. Tomás likes to send the whole repository: “Then it has everything.” But “everything” has no observation and no expected result: they are not in any file. It has many files that the task does not need, which cost tokens and give the model more wrong places to change. And it may include what must never leave your computer. ASSISTANT-SCOPE.md already says so: .env is never read.
Use a quick test before you send: would a new colleague need this to do this task? If not, leave it out. For a question about one function, the function is enough context. For a bug, the five kinds above. For a feature, the task brief and the files that it names.
Common mistake
The example file goes into the commit
Symptom: after the bug report is written, git status --short shows a file that you did not mean to keep:
?? minimal.csvA git add -A would put it in the commit, next to the real data in data/.
Cause: the minimal input is a working file, made in the project folder. Nothing in .gitignore excludes it, so Git offers it like any new file.
Fix: before each commit, read git status --short, and add files by name, as in step 6. Delete working files, or keep them outside the project. The bug report holds the example as text, so you lose nothing. ASSISTANT-SCOPE.md says the same for an assistant: it never adds a data file.
Your turn: context for a second symptom
Section titled “Your turn: context for a second symptom”Grace’s team runs the pending report of the Python course’s sample file:
python -m ticket_cleaner data/tickets.csv --status pending --output reports/pending.jsonRun it, and open reports/pending.json. Then answer: is this a new bug? Write the observation, the expected result, a minimal example and the file references that you would give an assistant. Do not commit anything.
Show the answer
The report has this:
"by_category": { "LOGIN": 1, "billing": 1},Ticket T-1010 has the category LOGIN in data/tickets.csv. In the Python course, clean_text() cleaned every category, so the same report had "login": 1. It is not a new bug: it is Grace’s bug, with another file.
- Observation: the command above, and
"by_category": {"LOGIN": 1, "billing": 1}. - Expected:
{"billing": 1, "login": 1}. - Minimal example: the two rows of
minimal.csvalready show it. You do not need a second example for the same cause. - File references:
ticket_cleaner/parsing.py(clean_category,to_ticket) andticket_cleaner/records.py(CATEGORY_ALIASES).
Add it to the bug report as one more observation, not as a new bug. Two reports of one cause make two fixes, and the second fix can break the first. The relevant-context prompt of the session above included this line.
Knowledge check
Section titled “Knowledge check”Check your understanding
Name the five kinds of relevant context for a bug, with Grace's bug as the example for each. Then name two things that you leave out.
Show the answer
- Observation:
python -m ticket_cleaner minimal.csv --output reports/minimal.jsongives"by_category": {"LOGIN": 1, "login": 1}. - Expected result:
{"login": 2}. - Minimal example: the two rows
T-1,open,login,1,OneandT-2,open,LOGIN,1,Two. - File references:
ticket_cleaner/parsing.pyandticket_cleaner/records.py. - Interfaces:
clean_category(value: object) -> str, called byto_ticket().
Leave out files that the task does not need, such as remote.py, and the whole data folder. Never include .env or its token, or real customers’ data.
Does your answer have the main points of ours?
Sign in and enroll in the course to save your answers. Every check counts toward the certificate.
Check your understanding
In the session bug-little-context, the assistant had report.py. Why could it not find the bug, even with a better prompt?
Show the answer
The bug shows in the report, but it is not in report.py. count_by_category() counts the text that it receives. The text gets its capital letters earlier, in clean_category() in parsing.py. The assistant never saw that file, and no repository map pointed to it. A better prompt with the observation and the expected result would help it ask the right question. To find the cause, it needs the file where the cause is. That is why you search the code, for example with grep -n category, before you choose the files.
Does your answer have the main points of ours?
Sign in and enroll in the course to save your answers. Every check counts toward the certificate.
Check your understanding
Tomás says: 'Give it the whole repository and the full export every time. More context is always better.' Give three reasons why not.
Show the answer
- The most important context is not in any file: the observed output, the expected result and the minimal example. A whole repository does not contain them.
- More text costs more tokens and gives the model more places to look, and more files that it may change. The relevant context of Grace’s bug was 3 files and two rows.
- Everything that you send leaves your computer. A whole folder can include
.env, a token or real customers’ data. The scope file says that the assistant never reads.env.
Does your answer have the main points of ours?
Sign in and enroll in the course to save your answers. Every check counts toward the certificate.
Recap
- The context of a request is everything that the model receives with it. It knows nothing else about your project.
- With one file, no map and “Fix it.”, the assistant changed nothing and asked for an example. The file that it had was where the bug shows, not where it is.
- Relevant context for a bug: the exact observation, the expected result, a minimal example, file references and interfaces. With them, the same model fixed the bug in
clean_category(), and all 5 checks passed. - Leave out what the task does not need, and never send a secret. Search the code to find the files; do not send everything.
- Your project has the bug report
docs/tasks/category-names-bug.md, committed. The bug stays until Module 4.
Next, Amira starts the feature. The code is new to her, so she asks for an investigation and a plan before any change.
Next: Break work into steps