Milestone 14

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

  1. Configuration contract. .env.example committed, 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. .env and credential files are gitignored.
  2. 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.
  3. 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.
  4. 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.md is the evidence.
  5. A deployment. The system runs somewhere a grader can reach it, deployed from the v1.0.0 tag, 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 in docs/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.
  6. 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.
  7. Release v1.0.0. An annotated, pushed tag; a published release with human-written notes; a CHANGELOG.md entry 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.
  8. Licensing, both directions. LICENSE at the repository root with its SPDX identifier in README.md, two sentences in docs/handoff.md defending the choice, and THIRD-PARTY-NOTICES.md inventorying your dependencies’ licenses with every real obligation named.
  9. The handoff package. docs/handoff.md, built from the provided template code/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.
  10. 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-issue and is referenced from the handoff guide.
  11. Bus-factor register. At least five things only you knew, each now closed by a guard, a document, or a landmine entry.
  12. 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:

#CommandYou should seeIf not
1git clone <url> && cd pantrypilot214 files
2./script/setupends with Setup complete.missing tool → README.md “Prerequisites”
3cp .env.example .env then fill it4 required values setownership table, docs/handoff.md §3
4npm run devlistening on http://localhost:8080port in use → change PORT
5npm test34 passing in ~12 stests 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)

CriterionPoints
Configuration contract complete and annotated; required values fail loudly; nothing secret in the tree or the history12
One reproducible setup path — fails fast, checks prerequisites, idempotent, abandoned alternative deleted14
Proof it ran on an environment that is not yours: where, when, how long, what broke10
Deployed and reachable from the tag (or the constraint argued in writing and the equivalent delivered); docs/deployment.md matches what you actually did12
Rollback written as numbered steps, rehearsed once, timed, with the migration question answered8
Release v1.0.0: annotated tag pushed, readable release notes, CHANGELOG.md tied to FR/DEF identifiers10
LICENSE chosen and defended; THIRD-PARTY-NOTICES.md inventory with obligations named8
docs/handoff.md: day-one path, week-one ramp, ownership table, five landmines14
Backlog hygiene: top five issues groomed with acceptance criteria; one good-first-issue6
Bus-factor register: five or more items, each closed by a guard, a doc, or a landmine4
Hours log and docs/ai-usage.md current and honest2
Total100

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.md on 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:

  1. 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.
  2. 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.
  3. 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.
  4. 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?
  5. 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.md should say. Write the notice.
  6. 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.md top 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.py before 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.md and 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-issue with 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.example is 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.0 tag 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.md cites FR and DEF identifiers
  • LICENSE in place with SPDX id in README.md; THIRD-PARTY-NOTICES.md inventory complete
  • docs/handoff.md filled with no placeholders left: day one, week one, ownership, five landmines
  • Top five issues groomed; one labeled good-first-issue and referenced from the handoff guide
  • Bus-factor register written, and every row closed
  • Hours log and docs/ai-usage.md current 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.