Capstone: ship a real feature with Claude Code
Monday, 9:00. Guests email hotels about 1,200 times a week asking for a late check-out, and almost a third never get an answer in time. Maya wants it in the product in two weeks. You direct Claude Code from the first line of the spec to the last number on the dashboard. Lina only checks.
One real feature, start to finish. Claude Code does the typing; you make every decision and decide when it's done.
- Problem
Guests can't request a late check-out in the app, so they email hotels; 1,200 requests a week, and almost a third never get an answer. StayHub wants it in the product in two weeks, built with Claude Code.
- Why the simple system fails
Asking the agent to "build late check-out" produces something that demos well and skips the decisions: when the guest is charged, who may accept, what happens across time zones, how it's rolled out, and how anyone would know it works.
- Engineering concept
Ship through a loop in which each stage leaves evidence: a spec with examples, a reviewed plan, a scoped diff, tests that can fail, a security pass, a deploy plan with a flag, and a metric that proves the guest problem is solved. Done is defined in advance.
- Technology
Specs with Given/When/Then examples, plan mode, CLAUDE.md, diff review, acceptance and regression tests, the five security questions, CODEOWNERS for payments, feature flags and gradual rollout, dashboards on the business outcome.
- Trade-offs
The full loop costs time on every stage; skipping stages is faster until the skipped one is where it breaks. Scale each stage to the risk of the parts it touches, and cut scope before cutting checks.
The problem
2 min- Maya · Product managerOnly 69% get an answer within 24 hours. I want it in the product in two weeks.
- Karim · CTOIt charges guests, so I don't want to read about it in a postmortem.
- Lina · Senior engineer, your mentorYou lead, start to finish. I'll only check your evidence after each stage.
The big idea
4 minRun the whole loop, each stage leaving evidence, and say "done" only when the guest outcome has moved.
You don't lay the tiles, but you approve the drawings, walk each stage, test the taps, and live with the bathroom a week before paying the last instalment. "Done" is yours to say.
How it works
5 minThe delivery loop is spec, plan, build and review, tests, security, deploy, monitor. Each stage is an earlier episode; here they run on one feature.
- 1Spec + definition of done
Rules, 8 examples, cuts. The lists the evidence needed before anyone says done, ending with the outcome metric: answered within 24 h, baseline 69%, target ≥ 85%.
- 2Plan, with owners
Plan mode first; any step through a one-way door (here, the charge) goes to its owner before code.
- 3Build + review
Small commits; anything outside the plan is reverted, especially dependency changes.
- 4Tests + security
Red, green, a deliberate break; then a fresh session asks the five security questions.
- 5Deploy + monitor
Env diff, additive migration, flag ramp with someone watching; then the outcome number after a week.
- 6Cut scope, not checks
When time is short, drop options (custom times, more languages), never tests, security or the flag.
Watch a decision being made
4 minYou ship late check-out; Lina checks each stage
Take late check-out from Maya's request to a measured result in two weeks.
- 1Spec and plan
Rules: charge on acceptance, hotel time zone, 24 h expiry, 12:00 and 14:00 only. The plan charged at submission "to secure payment": changed.
chargeAddOn()is insrc/payments, so Inès reviews; the request id becomes the idempotency key.Why: Five minutes on a plan caught the most expensive mistake before a line was written.
- 2Review, tests, security
A diff also refactored booking CSS and upgraded a date library: reverted. Break: UTC instead of hotel time; the New York example goes red. A fresh session finds the price sent from the browser: now taken from hotel settings on the server.
Why: Each stage caught something the others couldn't.
- 3Deploy gently
Env diff:
LATE_CHECKOUT_NOTIFY_TEMPLATEmissing in production, added. Ramp: 3 Lisbon pilot hotels → 10% → 100%, rollback rehearsed.Why: The missing-setting failure from Friday 17:30, caught by a two-minute diff.
- 4Prove it
After a week at 100%: 91% answered (from 69%), 64% accepted, 0.4% charge failures, ~770 late check-outs sold a week. Runbook written, owner named, every box ticked.
Why: Done is the checklist ticked with evidence, including the guest outcome.
In real life
3 minAmazon: working backwards
- Press release + FAQ written first
- The customer promise is fixed
- Publicly described by the company
Decide the outcome before building.
Basecamp: Shape Up
- Fixed time ("appetite")
- Scope flexes to fit
- Published as a free book
Fix the time, cut scope.
What goes wrong
3 minThe code can be perfect and the problem unsolved.
Watch the outcome metric against its baseline before each ramp step.
Guests can edit requests, prices included.
Prices and permissions come from the server.
The skipped check is where the next incident comes from.
Cut scope, and record the cut in the spec.
Trade-offs
3 min| Process | Fits when | You pay |
|---|---|---|
| Full loop on every part | Small features entirely about money or data | Heavy for text and layout |
| Loop scaled to risk | Most features: strict on charging, access, time | Honest risk rating per part |
| Prototype first | Testing demand behind a flag, no money or data | Prototypes become production |
- Karim · CTOTests are green. Skip the pilot: turn it on for everyone Monday.
- Maya · Product managerThen let's add custom times and reminder emails first, or hotels will ask.
- Karim · CTOThat's two more weeks.
Your job as tech lead
4 minClaude Code can write the code for this. You still own the decisions, and you have to know what good looks like to accept or reject its work.
- The rules and scope: when the guest is charged, whose clock decides, what happens without an answer, what's cut to version two.
- The definition of done, ending with the outcome metric, its baseline and its target.
- Each ramp step, decided by the numbers you named.
Read docs/specs/late-checkout.md and CLAUDE.md. Use plan mode: propose the files, an additive migration, the endpoints, and how a hotel's acceptance triggers chargeAddOn() with the request id as idempotency key. Don't edit yet. Decided: charge only on acceptance, hotel time zone, 24-hour expiry, 12:00 and 14:00 only. Everything behind late_checkout, default off. src/payments is stop-and-ask.
- Read the plan against the spec: charging moment, time zone, expiry, scope.
- The payment owner reviewed the plan; an idempotency test exists (event twice → one charge).
- Every line of the definition of done has evidence before anyone says done.
- The plan charges guests at a different moment than the spec.
- Prices or permissions taken from the browser's request.
- "Done" announced at deploy, before the outcome metric moved.
Check yourself
2 minNext: one feature is behind you. Karim makes you tech lead of StayHub's biggest project yet: a goal, a deadline, and no architecture.
Mark it complete to update your skill map.
Go deeper (optional)You don't need this to understand the lesson. Open it when a project needs the details: Technical deep dive, Visual diagram, Analogy, Why it matters, Check your understanding, Practice ladder, Explain it yourself.
Technical deep dive
Shipping late check-out (you lead; Lina checks each stage)
Take late check-out requests from Maya's request to a measured result in two weeks, directing Claude Code at every stage and keeping the evidence each stage requires.
- 1Spec and definition of done
Rules (charge on acceptance; hotel time zone; 24 h expiry; 12:00 and 14:00 only), 8 examples including the New York hotel, a double accept and a cross-partner request, and the definition of done with the outcome target (answered within 24 h ≥ 85%, baseline 69%).
Why: Lina's check: "Could Claude guess any of these rules differently?" Every rule written is a guess removed.
- 2Plan, with owners
Plan mode. Step 3 charges at submission "to secure payment": changed to charge on acceptance. The plan calls
chargeAddOn()insrc/payments, a stop-and-ask path, so Inès reviews that step and adds the request id as idempotency key.Why: Five minutes on a plan caught the most expensive mistake before a line was written.
- 3Build and review the diffs
Small commits. One diff also refactors the booking page's CSS and upgrades a date library: "Revert both from this branch; propose them separately."
Why: A diff that matches the plan is reviewable and rolls back cleanly; a dependency upgrade deserves its own review.
- 4Tests that can fail
One test per example, seen red, then green. Deliberate break: "compute times in UTC instead of the hotel's time zone". Example 6 (New York) goes red. Reverted.
Why: The suite proved it protects the rule that hurt guests in episode 1.
- 5Security pass
Fresh session reviews the branch with the five questions. Finding: the guest's request sends the price from the browser. Fixed: price comes from the hotel's settings on the server. Cross-guest and cross-partner tests return 404.
Why: What comes in is untrusted: a guest could have set their own price.
- 6Deploy gently
Env diff:
LATE_CHECKOUT_NOTIFY_TEMPLATEmissing in production, added. Additive migration. Flag ramp: 3 Lisbon pilot hotels → 10% → 100%, rollback rehearsed, you watching each step.Why: The same missing-setting failure as episode 4, caught by a two-minute diff.
- 7Prove it
Dashboard: answered within 24 h, acceptance, charge failures, errors. After a week at 100%: 91% answered (from 69%), 64% accepted, 0.4% charge failures, ~770 late check-outs sold a week. Runbook written; owner named. Every box ticked.
Why: Done is the definition of done, ticked with evidence, including the guest outcome.
| Stage | Evidence collected | What it caught |
|---|---|---|
| Spec | 8 examples, definition of done, cuts recorded | Rules the agent would have guessed |
| Plan | Approved plan; Inès's OK on the charge step | Charging at request time; missing idempotency key |
| Review | Diff matches the plan | Out-of-scope CSS refactor and library upgrade |
| Tests | Red → green; break caught | Time-zone rule protected (New York example) |
| Security | Five questions answered; 404 tests | Price sent from the browser |
| Deploy | Env diff; flag ramp; rollback rehearsed | Missing production setting |
| Monitor | Answer rate 69% → 91% after a week | Stale hotel contact emails (at 10%) |
Visual diagram
The late check-out feature and the loop that ships it. Click a component, or follow the walkthrough.
Analogy
- Renovating with a contractorSay what you wantShipping with Claude CodeSpec with examples
- Renovating with a contractorApprove drawings firstShipping with Claude CodeApprove the plan first
- Renovating with a contractorWalk through each stageShipping with Claude CodeReview each change
- Renovating with a contractorTest taps and drainsShipping with Claude CodeTests that can fail
- Renovating with a contractorLive with it a weekShipping with Claude CodeWatch the guest number
Where it breaks: a bathroom stays finished. Software keeps changing, so the proof (tests, alerts, dashboards) has to keep running after you're done.
Why it matters
An agent can build a convincing late check-out feature in an afternoon. The typing was never the hard part.
The rules are business decisions. Is the guest charged when they ask, or when the hotel says yes? Whose clock decides "11:00"? What if the hotel never answers? An agent fills each gap with a guess.
Every skipped step has a known failure. You've seen them all: tests that copied bugs, a hidden error, a leaked report, a Friday deploy, a refund paid twice.
Working isn't the goal. A feature with no errors that hotels never notice solves nothing. Only the guest number tells you.
Check your understanding
- 1.Security: five questions
- 2.Monitor the outcome against the baseline
- 3.Plan (plan mode), owners for one-way doors
- 4.Build in small commits, review each diff
- 5.Spec with examples
- 6.Deploy: flag, ramp, someone watching
- 7.Tests: red, green, deliberate break
Practice ladder
Which stage would have caught it?
Debugging Warm-upAnother team shipped "room service pre-order" with Claude Code in three days, skipping stages. For each problem they hit, trace which stage of the loop would have caught it, and how.
- Orders placed after 22:00 hotel time were charged but never sent to the kitchen.
- A guest could see another guest's order by changing the order number in the URL.
- The menu prices shown came from the browser's request, and one guest paid 0.10 € for breakfast.
- The feature crashed in production because a kitchen-printer setting existed only in staging.
- After launch, errors were 0% but pre-orders per day stayed near zero for two weeks; nobody noticed.
Complete the definition of done
Design PracticeComplete the definition of done for late check-out by filling the blanks.
- [ ] Every example has a test; seen ___, then ___; one ___ caught
- [ ] Diff reviewed: matches the ___; nothing ___
- [ ] Five security questions answered; ___ tests return 404
- [ ] ___ approved the charge step; test: ___ → one charge
- [ ] Deploy plan: ___ clean, ___ migration, flag ramp ___, rollback ___
- [ ] Dashboard live: ___ (baseline ___), acceptance, ___, errors
- [ ] After one week at 100%: ___ ≥ ___
- [ ] ___ written; ___ named
Run the loop: early check-in requests
Design StretchMaya's next request: early check-in. Guests ask to arrive at 10:00 or 12:00 instead of 15:00; the hotel can only accept if the room is free and cleaned; hotels charge ~20 €. Today ~900 email requests a week, 62% answered by the morning of arrival.
Produce, in short form: (1) five key examples for the spec, (2) the kick-off instruction to Claude Code, (3) the risk rating of the parts, (4) the outcome metric and target for "done".
Is late check-out done?
Decision StretchAlternative ending. After one week at 100%:
| Metric | Target | Result |
|---|---|---|
| Answered within 24 h | ≥ 85% (baseline 69%) | 88% |
| Charge failures on acceptance | < 1% | 2.6% |
| Errors | low | 0.1% |
| Late check-outs sold | none set | ~700 a week |
Charge failures mean the hotel accepted, the guest stayed late, but no payment was taken. Maya wants to announce "done" at Monday's all-hands. Write your decision: "We chose X over Y because…, accepting the risk of…".
Explain it yourself
A friend who has never coded asks: "If Claude Code writes all the code, what exactly is your job?" Answer using the late check-out feature.