Deployable Release v1.0 & Handoff Package
Apologetic question: "Who inherits what you built?"
Milestone 14 — Deployable Release v1.0 & Handoff Package
“because sometimes a person who has toiled with wisdom and knowledge and skill must leave everything to be enjoyed by someone who did not toil for it.” — Ecclesiastes 2:21 (ESV)
Chapter: Chapter 14 — Deployment, Reproducibility, and the Handoff
Week: 14 of 16
Due: End of Week 14. Budget ~15 hours; see the hours table in §14.13 of the chapter.
Submit: Push everything to your capstone repository, then post the repository link, the v1.0.0 tag URL, and the deployed URL (or your argued equivalent) to the Week-14 dropbox.
Where it lands in the final package: .env.example and script/setup (or Dockerfile / compose.yaml) at the repo root; docs/deployment.md; the rollback section of docs/runbook.md; CHANGELOG.md; LICENSE and THIRD-PARTY-NOTICES.md; docs/handoff.md; the annotated tag v1.0.0. In the Week-16 rubric these feed the reproducible setup, release tag, runbook, change log, license, and handoff guide lines — roughly a quarter of the 50% implementation-and-documentation grade.
AI policy: Open, with the spine rule and one hard condition. An assistant may draft your container definition, setup script, CI workflow, release notes, and license inventory. Nothing generated may be committed until you have executed it end to end in an environment that is not your development machine, and can explain every line. Log the use in docs/ai-usage.md — what you asked, what you accepted, what you changed, what you verified. You will be asked in Week 15 what a line of your Dockerfile does; “the assistant wrote it” is not an answer that survives a committee.
The Setup
It is a Monday morning in the spring after you graduate. Somebody at your school — a professor, a new student, a research group — decides your capstone is worth continuing. They open your repository for the first time. They cannot call you; your school email bounces and your phone number is not in the repo.
Everything they need is either in that repository or it is gone.
That is the entire scenario, and it is not hypothetical: it is exactly what happens to capstone projects, internal tools, and abandoned repos across the industry every week. Most of them die at this moment — not because the code was bad, but because the code was the only thing that got written down. The configuration lived in one person’s shell. The deploy was a manual sequence one person remembered. The API key was on one person’s account. The migration that has to run before the other migration was in one person’s head.
This week you make sure that does not happen to yours. You are the release engineer now: the person responsible for the distance between working code and running software, and for the distance between a running system and a system somebody else can operate. Everything below is graded on evidence rather than assertion — timestamps, transcripts, URLs, tags. “It should work” earns nothing this week, on purpose.
Learning Targets
You will demonstrate that you can:
- Separate configuration from code and publish the configuration contract that makes the separation usable.
- Handle secrets like a professional: none in the repository or its history, rotation procedure written and rehearsed, production values in a secret store.
- Make an environment reproducible by a script or a container, and prove it somewhere that is not your machine.
- Deploy a release from a tag, verify it, and get back to a known-good state on a timer.
- Version and publish a release with notes a stranger can read and a changelog tied to your requirement and defect identifiers.
- Meet your licensing obligations in both directions — what you grant, and what you owe every dependency you used.
- Assemble a handoff package that lets a competent stranger take the project over without you.
- Find and close the knowledge that exists only in your head.
The weekly status block — paste this into your submission comment
Every milestone submission carries these five lines. It takes two minutes, it is the same five lines every week, and it is the difference between an instructor who can help you in Week 6 and one who finds out in Week 14. Copy it into the Canvas submission comment when you submit — not into a document.
Shipped: what actually works this week, in one line
Cut: what I dropped or deferred, and where it went (backlog / change request / gone)
Hours: planned N / actual N (from docs/hours-log.csv)
Blocked on: the one thing in my way, or "nothing"
Ship confidence: green | amber | red — if amber or red, the one thing that would move it
Say red when it is red. A red in Week 6 is a conversation and a scope cut. A red discovered in Week 15
is a grade. Nobody has ever been penalised in this course for an honest amber; the only expensive answer is
the green that was not true.
Normal Tier
The bar. Every item below is a line on the Week-16 rubric, so treat this as depositing points, not spending time.
Required deliverables
- Configuration contract.
.env.examplecommitted, listing every value the code reads, each annotated with what it does, required or optional, where to obtain it, and a safe local value. Required values have no defaults; the app fails at startup with the variable’s name..envand credential files are gitignored. - Clean secrets. No credential in the working tree or the history. If one was ever committed, it is rotated — say so, with the date, in
docs/handoff.md. Say what you scanned with and what you found. - One reproducible setup path. Either a scripted setup or a container definition — not two, not one-and-a-half. It fails fast with readable messages, checks its prerequisites, is safe to run twice, and ends by telling the reader the next command and what they should see. The abandoned alternative is deleted from the repository.
- Proof of reproduction. The setup path ran on an environment that is not your development machine — a fresh cloud development environment, a new container from a bare base image, a classmate’s laptop, a lab machine. Record where, when, how long it took, and what broke the first time. A terminal transcript in
docs/deployment.mdis the evidence. - A deployment. The system runs somewhere a grader can reach it, deployed from the
v1.0.0tag, with a documented way to see logs and verify health. If your project cannot be publicly hosted — sensitive data, a hardware dependency, an institutional rule, or no budget and no payment method for a host — say so in writing indocs/deployment.md, name the constraint, and deliver the equivalent: a one-command local run, a recorded demo, and an honest estimate of what hosting would require and cost. Money is a legitimate constraint and is graded as one, not as a shortfall — that is the standing policy in Appendix A §A.8, and it is why the milestone table there flags Week 14 as the only week that reliably might cost anything. Read §A.8 before you conclude you have no path, though: it walks the free static hosting, the always-free virtual-machine tiers, and the student credits that have not required a card — every one of those dated to 2026 and needing you to verify the vendor’s current terms yourself — and most projects land on one of them. If none of them fit yours, argue the constraint and take the full points for the equivalent. A packaged CLI or library satisfies this with a published, installable artifact and install instructions somebody else verified. - A rehearsed rollback. Numbered commands in
docs/runbook.md, actually executed once against a real deploy, with the wall-clock time recorded and the database question answered honestly. - Release v1.0.0. An annotated, pushed tag; a published release with human-written notes; a
CHANGELOG.mdentry in Added / Changed / Fixed / Known issues form, with FR and DEF identifiers. If you shipped less than the specification promised, use an honest lower version and say why. - Licensing, both directions.
LICENSEat the repository root with its SPDX identifier inREADME.md, two sentences indocs/handoff.mddefending the choice, andTHIRD-PARTY-NOTICES.mdinventorying your dependencies’ licenses with every real obligation named. - The handoff package.
docs/handoff.md, built from the provided templatecode/handoff-template.md, filled completely: day-one path, week-one ramp ending in a merged change, accounts-and-costs ownership table, at least five landmines, the AI-dependency section if you have one, and the bus-factor register. - Backlog hygiene. Your top five open issues each carry a clear title, the requirement or defect ID, acceptance criteria, and the files most likely involved. One is labeled
good-first-issueand is referenced from the handoff guide. - Bus-factor register. At least five things only you knew, each now closed by a guard, a document, or a landmine entry.
- Hours log and AI log current, through this week, honestly.
What “proof” looks like — the standard, shown
Two deliverables get argued about every year, so here is the bar with the failing version beside it.
Deliverable 4, proof of reproduction. What most students submit:
Tested the setup on a clean machine and it worked fine.
Nothing in that sentence can be checked. Which machine, when, by whom, how long, and what broke the first time — because something always breaks the first time, and the fix is the interesting part. What earns the points:
Clean-environment run — 2026-04-22, 14:05–14:31
Environment: fresh cloud dev container, blank image, no local tooling
Operator: me, following README.md literally, no improvising
Attempt 1: FAILED at step 3. `npm ci` errored — package-lock.json was gitignored
since Week 4. Committed it (commit a91c4f2).
Attempt 2: FAILED at step 5. Migrations ran; seed script silently did nothing
because SEED_DEMO defaulted to false. Made it explicit in .env.example.
Attempt 3: PASSED. Clone→running: 9 min 40 s. Smoke test: 34 tests, 12 s.
That transcript is worth more than the working setup itself, because it proves the claim rather than asserting it — and the two defects it found are two afternoons your successor will never lose.
Deliverable 9, the day-one path. The version that scores near zero:
## Getting started
Clone the repo, install the dependencies, set up your environment, and run it.
Every noun in that sentence is a decision the reader now has to make alone. The version that scores:
| # | Command | You should see | If not |
|---|---|---|---|
| 1 | git clone <url> && cd pantrypilot | 214 files | — |
| 2 | ./script/setup | ends with Setup complete. | missing tool → README.md “Prerequisites” |
| 3 | cp .env.example .env then fill it | 4 required values set | ownership table, docs/handoff.md §3 |
| 4 | npm run dev | listening on http://localhost:8080 | port in use → change PORT |
| 5 | npm test | 34 passing in ~12 s | tests share one DB; do not parallelize |
Exact commands, exact expected output, and the recovery path for the step most likely to fail. That is the difference between a document and an instruction.
Normal-tier rubric (out of 100)
| Criterion | Points |
|---|---|
| Configuration contract complete and annotated; required values fail loudly; nothing secret in the tree or the history | 12 |
| One reproducible setup path — fails fast, checks prerequisites, idempotent, abandoned alternative deleted | 14 |
| Proof it ran on an environment that is not yours: where, when, how long, what broke | 10 |
Deployed and reachable from the tag (or the constraint argued in writing and the equivalent delivered); docs/deployment.md matches what you actually did | 12 |
| Rollback written as numbered steps, rehearsed once, timed, with the migration question answered | 8 |
Release v1.0.0: annotated tag pushed, readable release notes, CHANGELOG.md tied to FR/DEF identifiers | 10 |
LICENSE chosen and defended; THIRD-PARTY-NOTICES.md inventory with obligations named | 8 |
docs/handoff.md: day-one path, week-one ramp, ownership table, five landmines | 14 |
Backlog hygiene: top five issues groomed with acceptance criteria; one good-first-issue | 6 |
| Bus-factor register: five or more items, each closed by a guard, a doc, or a landmine | 4 |
Hours log and docs/ai-usage.md current and honest | 2 |
| Total | 100 |
Medium Tier (+ up to 25% extra credit)
Automate the discipline instead of performing it by hand. Pick what genuinely fits your project — three done well beat six done thinly.
- Continuous delivery on tag. A CI workflow that, when a
v*tag is pushed, builds the artifact, runs the test suite, and publishes the release. Ship the run URL. - A post-deploy smoke test. A command that hits the deployed system — not localhost — and fails loudly. Wired into the deploy step so a broken release cannot pass silently.
- A published, pinned container image, referenced by digest rather than by a moving tag, with the pull-and-run command in
README.md. - An independent clean-machine run. A classmate follows your
README.mdon their own hardware, unaided, on a timer, and writes the transcript. Include their words, including the parts that make you wince. - Secret scanning enabled on the repository, plus a written rotation procedure with dates and an owner for every credential.
- A generated dependency inventory (a software bill of materials, or your ecosystem’s license report) committed and regenerable with one command.
- A monitored deployment. A health endpoint, a log destination somebody other than you can read, and one alert that would actually reach a successor.
Hard Tier (+ up to 25% additional extra credit)
Required: The Succession Memo — two to three pages, written by you.
This is the deliverable no assistant can produce, because it requires knowing what you have not written down and being willing to say it. Address it to the engineer who inherits this project.
Cover all six:
- What I would tell you in person that is not in any document. The judgment calls, the parts of the system you do not trust, the shortcut you took in Week 12 that is still load-bearing. Be specific enough to be useful and honest enough to be uncomfortable.
- The decision I would revisit. Name one architecture decision record from Week 5 or Week 6 that you now believe was wrong, or right for a reason that has stopped being true. Say what you would choose today, what it would cost to change, and whether you would actually spend that.
- An honest bus-factor accounting. Not the register — the residual. After everything you wrote down this week, what is still only in your head? Everyone has something left. Naming it is worth more than pretending it is empty.
- The one-year cost of ownership, with the arithmetic shown. Hosting, database, domain, third-party APIs, model usage at a plausible volume. Dated, sourced from the vendors this week, and hedged where the vendor’s terms may change. Then the sentence students avoid: who pays this after I graduate, and what happens when nobody does?
- The deprecation plan. If nobody picks this up in six months, what should happen? Who archives the repo, what gets deleted, what happens to user data, and what the notice in
README.mdshould say. Write the notice. - The licensing defense under your institution’s policy. What your program’s intellectual-property rules actually say about coursework, how you confirmed it, and why your license choice is compatible with it.
Graded on judgment, honesty, and self-awareness. A memo that says “everything is documented and it costs nothing to run” scores zero, because it is not true of any software system that has ever existed.
Submission
Push to your capstone repository. The shape a grader will look for:
your-capstone/
├── README.md # updated: prerequisites, the ONE setup path, SPDX id
├── LICENSE
├── CHANGELOG.md # [1.0.0] with Added/Changed/Fixed/Known issues
├── THIRD-PARTY-NOTICES.md
├── .env.example # the configuration contract
├── .gitignore # .env, credentials, local databases
├── script/setup # …OR Dockerfile + compose.yaml — one path, not both
├── docs/
│ ├── deployment.md # target, deploy steps, verification, logs, transcripts
│ ├── runbook.md # + the rehearsed rollback, numbered and timed
│ ├── handoff.md # the handoff package
│ ├── release-checklist.md # walked, with the phase timings filled in
│ ├── hours-log.csv # current through Week 14
│ ├── ai-usage.md # this week's entries
│ └── succession-memo.md # Hard tier only
└── (your source, tests, and specs from Weeks 1–13)
Then post: the repository URL, the v1.0.0 tag URL, and the deployed URL or your argued equivalent.
Hints
- Start with the auditor, not the container. Run the Handoff Readiness Auditor before you touch anything. It will tell you where your project is weakest, and that is not the same for everyone. Then work its remediation list top-down.
- Do not build the deployment last. Hosting is where the surprise hours live — a DNS record, a build that behaves differently in CI, a database that will not accept a connection from outside. Start Tuesday, not Friday.
- Use the checklist as a checklist. Walk
code/release-checklist.mdtop to bottom and check boxes as you go. Its purpose is that it does not care what you are confident about. - Run
code/check_config.pybefore every commit this week. It catches the variable you added on Wednesday and never documented. - Rehearse the rollback while nothing is wrong. It takes twenty minutes on a calm Tuesday and it is impossible on a bad Friday.
- Write the landmines when you hit them, not at the end. Every time you catch yourself thinking “oh right, you have to do X first,” that is a landmine. Open
docs/handoff.mdand add it in the moment. - Do not host a CLI tool. Packaging is deployment for a command-line project. Spending eight hours putting TraceLens behind a web server would be a real, gradeable mistake.
- Give your successor a real first task. A
good-first-issuewith acceptance criteria is worth more than another paragraph of prose. It is the difference between a reader and a maintainer.
What Mastery Looks Like
A mastered handoff is boring to grade and that is the compliment. A grader clones the repository, reads twelve lines of README.md, runs one command, waits nine minutes, and the system is up with seeded demo data. They open docs/handoff.md and know within thirty seconds who owns the API key, what it costs, and what breaks first. They see a CHANGELOG.md with a Known-issues section that names two real defects the student chose not to fix and explained why. They find a rollback rehearsed on a date, with a time next to it. And in the landmines section they find five things that could only have been written by the person who built it — the kind of knowledge that is invisible in code and expensive to rediscover.
The tell is specificity. Amateur handoffs are reassuring: “the code is clean, reach out anytime.” Professional handoffs are useful: “run the seed script before your first login or the roles table is empty and every request 500s — see script/seed, and the guard added in ADR-0012.”
Coach’s Note — The instinct you will fight this week is the one that says being indispensable is a good position. It is not; it is a trap that costs someone else their time and eventually costs you your freedom to leave. Write it all down. Make yourself replaceable on purpose. That is what a senior engineer does, and it is the single clearest signal of maturity a capstone can send.
When You’re Done
-
.env.exampleis a complete, annotated contract; required values have no defaults - No secret in the working tree or the history; anything ever exposed has been rotated, with the date
- Exactly one setup path exists, works, and is the only one mentioned in
README.md - It ran on an environment that is not your machine — where, when, and how long are recorded
- Deployed from the
v1.0.0tag and reachable, or the constraint argued and the equivalent delivered - Rollback rehearsed once, numbered in the runbook, timed, migration question answered
- Annotated tag pushed; release notes published;
CHANGELOG.mdcites FR and DEF identifiers -
LICENSEin place with SPDX id inREADME.md;THIRD-PARTY-NOTICES.mdinventory complete -
docs/handoff.mdfilled with no placeholders left: day one, week one, ownership, five landmines - Top five issues groomed; one labeled
good-first-issueand referenced from the handoff guide - Bus-factor register written, and every row closed
- Hours log and
docs/ai-usage.mdcurrent through Week 14 - The auditor re-run; score and remediation list saved for comparison
A theological footnote. Ecclesiastes 2 is the honest complaint of a builder: “sometimes a person who has toiled with wisdom and knowledge and skill must leave everything to be enjoyed by someone who did not toil for it” (2:21, ESV). The Preacher is not being dramatic. You will leave this. Somebody who did not spend these 240 hours will inherit whatever you hand them, and they may be wise or a fool, and you do not get to choose. But notice what makes the complaint bite: the assumption that the point of the work was keeping it. Take that out and the same facts read as vocation rather than futility. Paul saw it from the other side — “like a skilled master builder I laid a foundation, and someone else is building upon it. Let each one take care how he builds upon it” (1 Corinthians 3:10, ESV). Someone else is building on it. Stated as fact, not tragedy. The only question left to a builder is how carefully he laid the foundation for the people he will never meet. Everything in this milestone — the annotated contract, the rehearsed rollback, the five landmines written down for a stranger — is that care, made concrete. It is love of neighbor at the level of a configuration file, and it is the last thing you will do for your project before you start learning to talk about it.