You remember that a course title contains “code,” but a little course-listing program finds nothing unless you remember the first word. One changed line can make that list useful: search anywhere in the title while keeping the same course IDs, spelling, order, and way to show everything.

That is the optional worked result in this book. Your own project is equally welcome. Perhaps its reminder sounds wrong, its note format needs tidying, or its default planning interval does not suit you. Choose one irritation in a small program you can already run. Make the improvement, use it, and actually restore the original before deciding which version to keep.

You work in three places: OpenCode Desktop for the request and code explanation, a text editor for the source and backup, and an operating-system terminal for running the local program. The curriculum page supplies the instructions; it does not run Python or change your files. Use an already-working OpenCode setup and model connection. If you still need the installation entry point, start at the AI Lab portal (opens in a new tab); this exercise assumes that setup is complete.

Learning objectives

By the end, you can:

  • Describe one useful change as a visible before-and-after result.
  • Follow input through the relevant variables, function, and output lines.
  • Give an agent a bounded edit request and inspect what it changed.
  • Preserve ordinary and edge-case behavior around the edit.
  • Restore a backup, demonstrate the old result, and explain which version you kept.

Core concepts

1. Structure — choose your small win

Finish this sentence: “When I use this program, I want ___ instead of ___.” For the listing: “I want to find a course by a word anywhere in its title instead of remembering the beginning.” This is more useful than “improve the search,” because you can name an input that distinguishes success from failure.

The approved app-payload-curriculum example supplies the design idea of improving a course listing. Here we use only that small slice. The supplied Python program and its three course records are synthetic teaching material, not an export or implementation of the production curriculum. You do not need its repository, a Payload installation, a database, or a framework build.

Choose your own project if it already has an equally small, visible change. Use its existing run instructions. If it is a website, retain its existing keyboard controls, labels, and validation as well as the output you care about. If you cannot run it yet, choose the supplied local example or the smaller note formatter later in this book. Getting an unfamiliar application deployed is a different task.

Before editing, preserve the working source. Duplicate the relevant file with a name such as courses-before.py, and leave that copy untouched. For a small multi-file project, copy its folder outside the working folder. If the program writes files, use copies of its input and output material too: restoring source code does not reverse changes to a spreadsheet, database, or remote account.

2. Understand — follow the short path

Input is what a program receives; output is what it produces. In the listing, you type a query and receive matching course lines in the terminal.

A variable is a name referring to a value. query holds the search text. A function is a named piece of work: course_listing takes course records and a query, then returns display text. print displays that text; returning a value and displaying it are separate steps.

The course records form a list, an ordered collection. Each record is a dictionary, which pairs names such as id and title with values. course["title"] reads that record's title. A for loop considers each course in the list. An if condition decides whether to include it.

Follow this path when you reach the complete source below:

Typed query → trim and case-fold → compare with each title
                                      ↓
                          matching original IDs and titles
                                      ↓
                         returned text → terminal display

strip() removes whitespace from the ends of the query, preserving the words and spaces inside. casefold() makes a copy suitable for matching without case distinctions. Neither operation rewrites the stored course title. Python's string-method documentation (opens in a new tab) explains these operations.

The original comparison uses startswith: it accepts a title only when its beginning matches the query. The improvement uses in: it accepts a title when the query occurs anywhere within it. This is literal substring search, not an AI answer. It cannot infer synonyms or repair misspellings. The empty string matches every title in both versions, so pressing Enter without typing remains the way to show all courses.

Indentation groups Python instructions. The line that appends a match must remain inside both the loop and the matching condition. The f before the display string lets expressions inside braces insert values. "\n".join(lines) combines matching lines with line breaks. If the list of matches is empty, the function returns a readable message instead.

3. Choose LLMs, Agents, skills, tools — one helper, one job

Use OpenCode with a coding-capable model you already have. The model interprets the request; the agent can inspect and edit project files through its tools. Your editor and the program's existing run command complete the job. This exercise needs no extra skill or dependency.

In OpenCode Desktop, work in the folder containing your practice file. Confirm the folder path before sending a request. Do not open a production project merely because the example mentions a curriculum application. Keep passwords, private course rosters, and unrelated files out of the material you provide.

Ask for the explanation and the bounded change together. The changed-lines view, often called a diff, helps you see what the agent actually edited. A persuasive explanation is not evidence that it saved the right file or that the program ran. Read the edit, save it, and use the run command yourself unless execution has explicitly been assigned to someone else.

Runnable exercise

Prepare the local listing

Use Python 3.6 or later already installed, an ordinary text editor, and a terminal. There are no packages, accounts, network requests, or file writes in this program. If Python is unavailable, use an already-running project instead of adding installation work to this exercise.

In your file manager, create a new practice folder such as one-code-change. In your editor, create a new plain-text file inside it named courses.py, not courses.py.txt. Paste the complete starting source below, without the Markdown fence marks, and save it. If that filename already contains your work, choose a new practice folder rather than replacing it.

COURSES = [
    {"id": "C01", "title": "Make useful code changes"},
    {"id": "C02", "title": "Read a small table"},
    {"id": "C03", "title": "Keep code changes reversible"},
]


def course_listing(courses, query):
    query = query.strip().casefold()
    lines = []
    for course in courses:
        if course["title"].casefold().startswith(query):
            lines.append(f'{course["id"]} | {course["title"]}')
    if not lines:
        return "No matching courses."
    return "\n".join(lines)


if __name__ == "__main__":
    query = input("Title search (Enter for all): ")
    print(course_listing(COURSES, query))

The final if __name__ == "__main__": means “ask for input when this file is run directly.” It also lets the small check file below import the function without opening an input prompt.

Open a terminal in this practice folder. You can use cd "path to your folder" at the terminal prompt to reach it. Run the command your installed Python provides:

  • Windows: py courses.py; if your installation instead provides Python 3 as python, use python courses.py.
  • macOS or Linux: python3 courses.py.

Commands belong at the operating-system terminal prompt. If you see Python's >>> prompt, enter quit() first. After each search, the program exits; run the same command again for another search.

Start with Make. The expected result is:

C01 | Make useful code changes

Run again and enter code. The original program should display:

No matching courses.

That is the limitation you are changing: two titles contain the word, but neither begins with it. Run again and press Enter without typing. You should see all three records, in their source order:

C01 | Make useful code changes
C02 | Read a small table
C03 | Keep code changes reversible

Now use the file manager to duplicate courses.py as courses-before.py in the same folder. This is the known starting version. Do not ask the agent to update it along with the working file.

Ask for the one useful improvement

Send this in the OpenCode Desktop conversation for the practice folder:

I'm making one useful change to my local course-listing program.
File: courses.py. Backup: courses-before.py; leave it untouched.
Use the existing Python 3 run command for this folder.

Current behavior: searching Make finds C01, but searching code
finds nothing because the match only checks the start of a title.
Wanted behavior: code should find C01 and C03, in that order.
Match literal text anywhere in the title, ignoring case and
whitespace at the ends of the query.

Read the file and explain the input, output, variables, function,
and exact comparison involved, using code as the example input.
Then change only the comparison needed for this improvement.
Preserve blank-query show-all behavior, the no-match message,
original IDs, original title spelling, and source order.
Do not change the course records or add dependencies or features.

Show the changed lines and explain how to run and restore the file.
Do not execute it; I will run the checks after the edit is complete.
Distinguish expected results from results actually observed.

For your own project, replace the paths, before-and-after example, and preservation requirements with your actual details. Name the one function or output you want explained if you already know it. “Preserve unrelated behavior” is helpful, but naming the behavior you rely on makes the request much easier to judge.

Build — inspect and use the change

In courses.py, this original line:

        if course["title"].casefold().startswith(query):

should be replaced by this line, at the same indentation:

        if query in course["title"].casefold():

The complete starting source plus this replacement is the improved program. Everything else stays as supplied. If the agent sorted the courses, renamed IDs, rewrote the input loop, or added an installation step, the change has exceeded the request. Ask it to reduce the edit before running it.

Save the file. Run it and enter code. The expected useful result is:

C01 | Make useful code changes
C03 | Keep code changes reversible

You can now copy those two course references into your learning notes without remembering how their titles begin. This is the result you wanted; the following checks protect it.

Complete the edit before doing one check pass. Restart the program for each input below. Quotes in the table show spaces; do not type the quote marks.

InputExpected improved behaviorWhat it protects
codeC01, then C03, with the exact lines aboveThe new anywhere-in-title match
" CoDe "The same two linesCase handling and trimming
MakeOnly C01An old successful query still works
Enter alone, then " " on another runAll three original lines, in orderClearing the search still shows everything
biologyNo matching courses.A readable empty result
C01No matching courses.This remains title search, not ID search
code changesC01, then C03A literal phrase can match
code changes with two internal spacesNo matching courses.Internal spaces are not silently rewritten

For a small repeatable check, create a new file named check_courses.py beside courses.py after the edit is finished. This is complete check code, not something to append to the program:

from courses import COURSES, course_listing

original_records = [course.copy() for course in COURSES]
all_courses = (
    "C01 | Make useful code changes\n"
    "C02 | Read a small table\n"
    "C03 | Keep code changes reversible"
)
code_courses = (
    "C01 | Make useful code changes\n"
    "C03 | Keep code changes reversible"
)
assert course_listing(COURSES, "code") == code_courses
assert course_listing(COURSES, "  CoDe  ") == code_courses
assert course_listing(COURSES, "Make") == "C01 | Make useful code changes"
assert course_listing(COURSES, "") == all_courses
assert course_listing(COURSES, "   ") == all_courses
assert course_listing(COURSES, "biology") == "No matching courses."
assert course_listing(COURSES, "C01") == "No matching courses."
assert course_listing(COURSES, "code changes") == code_courses
assert course_listing(COURSES, "code  changes") == "No matching courses."
assert course_listing([], "code") == "No matching courses."
assert course_listing([], "") == "No matching courses."
assert COURSES == original_records
print("Course-listing checks passed.")

Run py check_courses.py, python check_courses.py, or python3 check_courses.py, using the same Python command as before. Expected output is Course-listing checks passed. An assert compares actual and expected values and stops with an error when the condition is false. Run the ordinary command as shown, without Python's optimization flags, which can disable assertions. The check also covers an empty source list and confirms that searching did not alter the records. It complements the terminal interaction; it does not demonstrate keyboard input or undo.

Recover, then actually undo

If the result differs, stop adding features. Compare the exact input, saved file, and run command with the instructions. Use one focused correction request:

File and run command: [exact values]
Input: [exact text, including relevant spaces]
Expected output: [what should happen]
Actual output or error: [paste the terminal text]

Explain the cause and make the smallest correction within the
original change. Leave the backup untouched. Do not expand scope.

Common recoveries are local:

  • Command unavailable: use your installation's known Python 3 command or switch to your already-running project. The manuscript does not establish that Python is installed.
  • Cannot open file: check the terminal's folder and the real extension. A file saved as courses.py.txt is not the requested filename.
  • SyntaxError or IndentationError: check straight quotes, the condition's final colon, and indentation against the source. Do not paste the backtick fence marks into Python.
  • Still no matches for code: save courses.py, verify that the command names that file rather than the backup, and inspect the comparison. Editing a copy in another folder will not affect this run.
  • AssertionError: read the failing line in check_courses.py; compare its expected text with the function output. Do not delete an assertion simply to get a success message.

Now demonstrate restoration even if everything worked. If you want to retain the edited version, first duplicate it as courses-after.py. Open courses-before.py in the editor, copy its entire contents over courses.py, and save. Leave the backup itself intact. Run courses.py again:

  1. code should again produce No matching courses.
  2. Make should still produce the C01 line.
  3. Enter alone should still show all three courses in the original order.

That is evidence of undo, not just possession of a backup. The improved-version checker is expected to fail on the restored original at its code assertion; do not mistake that for a failed restoration. You can now keep the original or reapply the single comparison change and confirm the two code results once more. Record the version you actually leave in courses.py.

Smaller alternative: keep the pocket note route

If a copyable checklist is more useful to you than a course listing, do this alternative instead. The same explain–edit–use–undo method applies. Create a new plain-text note.py in your practice folder with the complete original source:

def format_note(text):
    text = text.strip()
    if not text:
        return "Please enter a note."
    return f"- {text}"


note = input("Your note: ")
print(format_note(note))

Run py note.py, python note.py, or python3 note.py with your installed command. Type Pack headphones and press Enter. Expect - Pack headphones. Duplicate the file as note-before.py before editing.

Here note holds the input, format_note returns the formatted string, and print displays it. strip() removes padding; if not text catches an empty or spaces-only note. The last return controls the useful prefix. Ask OpenCode to explain those lines and change only that return to:

    return f"- [ ] {text}"

Run the edited program with Pack headphones, then Pack headphones . Both should produce - [ ] Pack headphones. Paste the result into a Markdown-checklist-capable notes app, or use it as plain text. Run again with Enter alone and with only spaces: both should still produce Please enter a note. Internal spaces in a note remain as typed.

Copy the entire untouched note-before.py contents back over note.py and save. Confirm that the ordinary and padded note again produce - Pack headphones, and the blank cases still produce the readable message. Reapply the prefix change if you want to keep the checklist behavior. This program only displays text; it does not save notes or update your notes app for you.

Exit check

Keep one inspectable local change packet in your practice folder: the working source, untouched before-copy, and a short change-note.md. Include an after-copy if the working file ends in its restored state. For your own multi-file project, the equivalent folder copies are sufficient.

Write the note using actual observations, not the expected outputs copied from this book:

Useful change:
Working file and run command:
Backup path:
Relevant input → function → output:
Exact changed line(s) and why:
Ordinary input and observed before/after output:
Preserved behavior and observed edge-case output:
Restoration action and observed original output:
Version now kept in the working file:
Remaining limitation:

The packet passes when another reader can locate both versions, see the useful difference, understand why the changed lines cause it, and find your evidence that important existing behavior survived and restoration worked. It fails if only the agent claims success, the original is lost, or the new result depends on unrelated unexplained edits. A checklist note or a clearer reminder can pass just as well as the course listing.

Choose a possible next personal improvement, such as a heading you regularly type, but finish this change before starting it. When teammates will rely on the result, continue with T08-L02: Code without being a developer (opens in a new tab). Shared software brings review and operating responsibilities beyond this own-work exercise.

Source notes

  • Original edition: T08-L01 public baseline (opens in a new tab). The supplied completion brief records its body SHA-256 as b98584264034898802f2ebda9bcb498c34d2592541b00abbe860fa356fcb53d7. This revision used the full supplied source manuscript; it did not independently fetch or re-hash the public edition.
  • Historical Python sources: the original manuscript records official documentation fetched on 9 September 2026 for running scripts (opens in a new tab), input and print (opens in a new tab), and defining functions (opens in a new tab). Those dates describe the original source work, not a new check.
  • New bounded source consultation: on 11 September 2026, this author fetched Python's Built-in Types documentation (opens in a new tab) and read the relevant strip, casefold, startswith, and substring-membership guidance under find. These support the changed comparison and its explanation, not a claim that this manuscript's programs were executed.
  • Example origin: the owner-approved app-payload-curriculum design slice motivated a small course-listing improvement. All C01–C03 records and the local listing source are newly written synthetic examples. They do not establish production features, downloadable software, or institutional use.

Unknowns and limitations

The revised listing, its check file, and the retained note example were not executed in this authoring session. All displayed program results are expected results awaiting the coordinator's consolidated verification and the learner's own run. No installation, OpenCode Desktop interaction, screenshot capture, printing, independent reader acceptance, publication, or classroom outcome was observed here.

The listing expects the supplied shape: an ordered list of records with string id and title values. It does not validate imported data. It searches titles literally, keeps internal spaces significant, and does not provide ranking, word-boundary matching, accent normalization, typo correction, or persistence. Keep those limits visible when choosing whether this change suits your own project. A passing local example does not establish that a production application's search has the same requirements.

How this book was made

Coordinator editorial update, 11 September 2026: The independent Terra reader accepted this revision. The account below records authoring-stage work; learner execution and classroom outcomes remain unobserved.

The original manuscript credits Astra / OpenAI (openai/gpt-6-astra) with its writing and scope work. Its contributions retained here include learner project choice, the complete pocket note formatter, input/function/output explanations, the bounded OpenCode request, edge-case preservation, and actual undo. The historical internal paragraphs after its first official-Python source paragraph were not carried into the learner lesson, and their earlier code-check claim is not evidence for this revision.

This example-led revision was authored on 11 September 2026 by Astra / OpenAI, with exposed model ID openai/gpt-6-astra, in one fresh OpenCode author session. The new contributions are the synthetic course-listing result, its one-line search improvement, preservation cases, repeatable check source, and integrated recovery and handoff guidance. No other author or independent reviewer participated in this session; the supplied original attributes no Sol or Luna contribution to this book.

The author read the assigned brief, style guide, learnings, template, and complete original manuscript, then wrote only this replacement draft. Execution and acceptance are handed to the coordinator after all assigned manuscripts are integrated. Token, cache, reasoning, and billing counters are unavailable, so cost is unknown. The practical production lesson is the same as the learner's: a small visible behavior change can carry substantial teaching when its starting state, exact edit, preserved behavior, and way back are explicit.