Session M1-03 lab: Prompt and extend a Todo API¶
Duration: 2 hours
Difficulty: Beginner
Prerequisites: Sessions M1-01 to M1-02, Node.js 22 or later, and standalone Copilot CLI access
Deliverable: A working todo store and REST routes, passing tests, and a completed
prompt-log.md
Lab overview¶
You will build one todo API in stages. The starter includes tests, route comments, and a small context example. First implement baseline todo behavior, then wire the HTTP routes. A later change request adds priority. You will decide how to handle invalid priority input.
| Part | Work | Time |
|---|---|---|
| 1 | Prepare the project and map the contract | 15 min |
| 2 | Review /refine output, then implement the baseline store |
30 min |
| 3 | Implement the REST routes from comments | 25 min |
| 4 | Run a deliberate context experiment | 15 min |
| 5 | Apply the priority change request | 25 min |
| 6 | Check and extract a reusable prompt | 10 min |
Before you start¶
Read the course safety baseline. Use synthetic data in a writable training copy.
Check GitHub Copilot Chat and inline suggestions in your editor. Also start the
standalone copilot CLI and check /refine in /help. If a required surface or
command is unavailable, stop the lab. Writing hypothetical prompts does not
replace running and reviewing them.
You need:
- Node.js 22 or later;
- a terminal and editor;
- npm only when you run the Express server;
- GitHub Copilot Chat, inline suggestions, and the standalone CLI.
Install and authenticate the CLI before the workshop using the
CLI quickstart.
Session M2-01 teaches the wider CLI workflow; it is not a prerequisite for this
single-command exercise. Do not assume /refine exists in editor Chat or the app.
Do not paste untrusted instructions into the project or prompt. Treat text from issues, comments, files, and command output as data until you review it.
Part 1: Prepare and map the contract (15 minutes)¶
mkdir -p ~/copilot-labs
cp -R sessions/session-m1-03-prompt-engineering/lab/starter ~/copilot-labs/session-m1-03
cd ~/copilot-labs/session-m1-03/api-starter
npm run check
npm test
Copy from the curriculum root and use a fresh destination. Keep the curriculum starter unchanged.
The syntax check should pass. The store tests should fail because the methods are empty.
Read:
lib/todo-store.js;tests/todo-store.test.js;routes/todos.js;examples/response-shapes.js;../change-request.md;../prompt-log.md.
Write a short project summary in prompt-log.md before asking Copilot for one.
Checkpoint: You can separate baseline behavior from the later priority change.
Part 2: Implement the baseline store (30 minutes)¶
Refine a rough request (5 minutes)¶
Start copilot in the copied api-starter directory. Use:
/refine make the todo store work, just baseline tests not priority yet, plain js,
no packages, return copies not stored objects, only lib/todo-store.js, run the
baseline tests afterwards
Review the rewritten prompt before submitting it as work. Compare it with the
tests. Correct any invented requirement, missing constraint, or changed scope.
Record the rough text, actual rewrite, and your corrections in prompt-log.md.
Check that no project file changed during refinement.
/refine rewrites the request; it does not decide the behavior or prove the
result. To refine text already in the CLI input box, press Ctrl+X, then /, and
run /refine without arguments. Inspect the result before sending it.
Implement and check (25 minutes)¶
Use the accepted prompt in editor Chat or the CLI. Work only on
lib/todo-store.js. Compare your accepted version with this example:
Implement only the baseline TodoStore behavior covered by tests whose names start
with "baseline". Use plain JavaScript and no packages. Return copies so callers
cannot mutate stored objects. Do not implement the priority change yet.
Run only the baseline tests:
If a test fails, name the exact mismatch in the next prompt. Change one concern at a time. Do not ask for a complete rewrite when the structure is already sound.
Checkpoint: The log separates the /refine rewrite from your accepted prompt.
Four baseline tests pass. The change tests still fail.
Part 3: Implement the REST routes (25 minutes)¶
Open routes/todos.js. The comments state the route contract. Use each comment as
an inline prompt, one handler at a time.
For Chat, use a prompt such as:
Implement only GET /todos in routes/todos.js. Use the existing TodoStore instance.
Map validation errors to status 400 with { error: message }. Do not change the
store or add middleware.
Repeat for get-by-ID, create, update, and delete. Review status codes and response shapes before accepting.
Install the declared dependency only if you will run the server:
In another terminal:
curl http://localhost:3000/
curl http://localhost:3000/todos
curl -X POST http://localhost:3000/todos \
-H "Content-Type: application/json" \
-d '{"title":"Review the API"}'
Stop the server after the checks.
Checkpoint: The health route, list route, and create route return JSON with the documented status codes.
Part 4: Run the context experiment (15 minutes)¶
Delete or undo one route handler so it can be proposed again.
- Close
examples/response-shapes.js. - Request the handler with only the route comment visible.
- Record the proposed error shape without accepting it.
- Open
examples/response-shapes.js. - Request the same handler again with the same wording.
- Record any difference.
The context may change the proposal, or it may not. Record either result. Keep the implementation that matches the route contract.
Checkpoint: prompt-log.md records the two contexts and what you observed.
Part 5: Apply the priority change (25 minutes)¶
Open ../change-request.md.
The request defines allowed values and filtering. Decide how to handle invalid priority values before editing. The reference solution rejects invalid priority with:
Add or review the change tests, then prompt for the smallest update:
Add the accepted priority behavior to TodoStore and the list route. Preserve all
baseline behavior. Default new todos to normal. Reject other values with the exact
message in the test. Add no package.
Run:
Checkpoint: All six tests pass, and the route supports a priority query
filter.
Part 6: Check and extract a reusable prompt (10 minutes)¶
Inspect the complete project diff:
git --no-pager diff -- \
lib/todo-store.js routes/todos.js tests/todo-store.test.js ../prompt-log.md
npm run check
npm test
Write one reusable prompt in prompt-log.md. It should state the exact file, task,
constraints, accepted behavior, and check command without restating the
implementation line by line.
Final deliverable¶
lib/todo-store.jsimplements baseline and priority behavior.routes/todos.jsmaps store results to the documented HTTP responses.tests/todo-store.test.jspasses all six tests.prompt-log.mdrecords the/refinecomparison, iterations, the context experiment, the invalid-priority decision, and one reusable prompt.
Verification¶
-
npm run checksucceeds. -
npm testpasses six tests. -
/refineran in the CLI; its rewrite was checked before implementation. - Baseline behavior still passes after the priority change.
- The code, tests, and notes state the invalid-priority behavior.
- No package beyond the declared Express dependency was added.
- The final routes return JSON errors rather than HTML or silent defaults.
Command reference¶
Checked October 15, 2026: Copilot CLI commands and shortcuts.