In this article
A focused AI-generated patch should change the requested behavior while preserving the contracts around it. Add case-insensitive ordering to a task selector, then check what a broad rewrite would silently change.
Define the feature and the behavior around it
Suppose a Python helper returns open task records from an input list. The feature request is to display those tasks in case-insensitive title order. A coding assistant could replace the helper, add a task class, normalize stored titles, and introduce a sorting abstraction. Each extra decision would increase the behavior you need to understand before accepting the feature.
For this original illustrative example, the input is a list of dictionaries with valid string titles and an open boolean. The existing helper returns a new list containing the original open record objects. It preserves their input order and leaves the input untouched. The requested change replaces that output ordering only: use Python casefold keys and preserve input order when keys compare equal.
Write those constraints beside the task. Closed records must remain excluded, displayed titles must retain their spelling, and the caller's list must keep its order. The exercise assumes valid records; adding missing-title recovery or storage validation is a separate feature decision.
def open_tasks_before(tasks):
return [task for task in tasks if task["open"]]
Read a broad rewrite as several behavior changes
Consider the proposal below. It produces alphabetized output in a happy-path demonstration, but it also sorts the caller's list in place and reconstructs each dictionary. The caller loses its original ordering, and the returned objects no longer have the same identities. Those are observable changes even when the displayed names look reasonable.
Python documents that list.sort modifies its list, whereas sorted constructs a new list. That distinction is enough to question the mutation here; there is no need to speculate about the assistant's intent. Python sorting techniques The extra dictionary construction is a separate issue arising from this example's identity contract.
The proposal also uses lower rather than the agreed casefold operation. Python describes casefold as suitable for caseless matching and gives the sharp-s character as a distinction from lower. Python string casefold reference Keep the review specific: the chosen key violates this task's rule, rather than being universally wrong for every application.
def open_tasks_broad(tasks):
tasks.sort(key=lambda task: task["title"].lower())
return [dict(task) for task in tasks if task["open"]]
Give the assistant a bounded revision request
Ask for a revision with the relevant function and its immediate contract: “Add casefold-based title ordering to the returned open tasks. Keep original record objects, preserve equal-key order, and leave the input list unchanged. Use the standard library. Do not change callers, filtering, stored titles, or error behavior.” These constraints describe observable requirements rather than an arbitrary limit on changed lines.
The focused implementation filters into a new list and sorts that list through sorted. Python guarantees stable sorting, so records with equal keys retain their order. Python sorting techniques Computing a comparison key does not require rewriting the value that the user sees. The record title stays as supplied.
This implementation introduces no new reusable abstraction because there is only one ordering rule in the exercise. If another caller needs a different rule, inspect that requirement before generalizing. A small patch is valuable when its scope matches the feature; line count by itself is not a correctness argument.
def open_tasks(tasks):
selected = [task for task in tasks if task["open"]]
return sorted(selected, key=lambda task: task["title"].casefold())
Check identities and input state as well as output
Build a fixture whose original order differs from the requested order. Put a closed record among open records and include two titles with equal casefold keys. Here the original ID order is 30, 10, 20, 40, 50. The hand-selected output order is 20, 40, 10, 30: two alpha titles, then beta, then Zulu. Record 50 is closed and must be absent.
Paste the focused implementation above this check and run the file. The assertions cover the output IDs, unchanged input values and order, and original record identities. A broad implementation can pass the first assertion while failing a later one, which is why checking only the rendered list is insufficient.
For a second, smaller fixture, STRASSE and Straße compare equally under the specified key. The literal expectation keeps their original order. That fixture distinguishes the requested operation from lower without computing the expected result by invoking the production sorting expression again. Python string casefold reference
def check_selector(select):
tasks = [
{"id": 30, "title": "Zulu", "open": True},
{"id": 10, "title": "beta", "open": True},
{"id": 20, "title": "alpha", "open": True},
{"id": 40, "title": "ALPHA", "open": True},
{"id": 50, "title": "aardvark", "open": False},
]
before = [dict(task) for task in tasks]
originals = {task["id"]: task for task in tasks}
result = select(tasks)
assert [task["id"] for task in result] == [20, 40, 10, 30]
assert tasks == before, "input values or ordering changed"
assert all(task is originals[task["id"]] for task in result)
equal_keys = [
{"id": 1, "title": "Straße", "open": True},
{"id": 2, "title": "STRASSE", "open": True},
]
assert [t["id"] for t in select(equal_keys)] == [1, 2]
assert select([]) == []
assert select([{"id": 3, "title": "closed", "open": False}]) == []
check_selector(open_tasks)
Connect every changed line to a requirement
Now run the same check against the broad proposal. The first fixture catches an input mutation. To investigate additional defects, use fresh input for each check instead of reusing the list the proposal already changed. Observe record identity separately, then run the equal-key fixture to expose the key mismatch. One early assertion failure should not be mistaken for a complete inventory of defects.
Review the patch after verification. The selector and focused tests should explain the change; unrelated configuration, dependency, or caller edits need their own reason. If the assistant included an opportunistic cleanup, separate it unless the feature actually depends on it. This reduces the set of assumptions a reviewer must accept at once.
Preserve existing tests and their expectations except where the ordering requirement deliberately changes them. When updating an expected order, explain how it follows from the agreed key and stable tie behavior. A test update should document the feature, not erase inconvenient evidence about a regression.
Keep the limits of the ordering rule explicit
Casefold-based ordering is the rule of this example, not a promise of culturally appropriate alphabetical order in every language. Locale-specific collation, accent treatment, and normalization need product requirements and additional evidence. Avoid adding such behavior merely because the assistant calls it a Unicode improvement.
The result is a new list containing shared records. Later mutation of one of those dictionaries can still be visible through another reference. That is intentional under the identity contract; this helper is not producing an isolated snapshot. If callers require snapshots, agree on copying semantics and test them as a separate change.
The straightforward implementation materializes a filtered list and a sorted list. For a large dataset, measurement and a different data-access design may be appropriate. No benchmark is claimed here. Keep the acceptance statement to what the exercise establishes: requested ordering, stable ties, preserved filtering, and no mutation of the supplied list or records.
Common questions about focused AI-generated changes
How small should the patch be? Small enough that every changed behavior is justified by the request and supported by checks. A longer change can be necessary when the contract spans several layers. A short change can still hide a destructive mutation.
Should I always reject refactoring? No. Separate a useful refactor when it has an independent purpose. If a refactor is required for the feature, explain that dependency and verify the old behavior before adding the new behavior.
What should I report after accepting the patch? Name the ordering rule, the preserved contracts, the executed checks, and the remaining limits. In an interview, use an assistant only when explicitly permitted, and explain why you accepted its final suggestion instead of treating a confident summary as evidence.
Sources & editorial notes
This article was authored with AI using primary-source research and an automated technical review. It has not been reviewed by a human. Code examples are illustrative; run and verify them in your own environment.
- Python sorting techniques
Documents sorted, list.sort, key functions, and stability of equal-key ordering. Retrieved October 20, 2026; evergreen documentation, not a new announcement.
- Python string casefold reference
Explains caseless matching and the difference between casefold and lower. Retrieved October 20, 2026; evergreen documentation, not a new announcement.
Put the reading into practice
Work through an existing repository, review AI suggestions, and test the decisions behind your changes.
Explore practice problems