Milestone 7

Documentation Set, Deployable Release & Handoff Package

Apologetic question: "What does it mean to entrust your work to another?"

Milestone 7 — Documentation Set, Deployable Release & Handoff Package

“…what you have heard from me in the presence of many witnesses entrust to faithful men, who will be able to teach others also.” — 2 Timothy 2:2 (ESV)

Chapter: Chapter 7 — Document, Deploy, and Hand It Off Week: 7 of 8 · budget ~20 hours; see the hours table in §7.12 of the chapter. Due: End of Week 7. Both clean-machine runs must actually happen before the deadline, not be described as a plan. Submit: The repository link, the commit SHA of the documentation commit, the v1.0.0 tag URL, and the deployed URL (or your argued equivalent), to the Week-7 dropbox. Where it lands in the final package: README.md, LICENSE, CHANGELOG.md, .env.example, script/setup (or Dockerfile / compose.yaml), docs/architecture.md §0, docs/runbook.md, docs/handoff.md, docs/adr/README.md, the successor-facing section of docs/ai-usage.md, docs/clean-machine-test.md, and the annotated tag. In the Week-8 rubric these feed the documentation, reproducible setup, release tag, runbook, change log, license, and handoff lines — the largest single block inside the 50% implementation-and-documentation component. See Appendix D. AI policy: Open, with the spine rule and two hard conditions. An assistant may draft, restructure, and tighten any document here, and may draft your container definition, setup script, CI workflow, release notes, and license inventory. (1) Nothing generated may be committed until you have executed it end to end, and you can explain every line. (2) The clean-machine test is closed to AI — a model cannot be your tester, and its confident “this should work” is exactly what the test exists to disprove. Every AI-drafted section gets a row in docs/ai-usage.md naming what it drafted and what you found wrong when you ran it.


The Setup

It is a Monday morning in the spring after you graduate. Somebody decides your capstone is worth continuing — a professor, a new student, a research group, an employer who saw the repository on your résumé. They open it for the first time. They cannot call you: your school email bounces and your number is not in the repository.

Everything they need is either in that repository or it is gone.

That is the entire scenario, and it is not hypothetical. It is what happens to capstone projects, internal tools, and abandoned repositories across the industry every week. Most of them die at exactly 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.

There is a second reader, and this one is certain rather than hypothetical: the grader who opens your repository next week. Same fifteen minutes, plus a rubric. Every documentation line on that rubric is a line you can earn this week, while there is still time to fix what you find, or lose in Week 8, when there is not.

So this week you produce the artifacts that speak for you in both rooms, and then you run the only test that tells you whether they work: you put your repository on a machine that is not yours, and then into the hands of a real person, and you sit silently while they use it. The documents are the deliverable. The runs are the proof.

The milestone is not “write documentation.” It is prove that a stranger can run, operate, and take over your project without you — and record honestly what happened when you tried. Everything below is graded on evidence rather than assertion: timestamps, transcripts, URLs, tags. “It should work” earns nothing this week, on purpose.

A word on scope. The two-thirds rule applies to documentation too. You committed to three or four Must features, so four runbook failure entries is the bar, not eight; five landmines, not fifteen; one page of architecture, not six. Do not pad. A complete, honest, small set beats a sprawling one with holes in it, and a grader finds the holes first.


Learning Targets

You will demonstrate that you can:

  • Write a README to a professional standard — nine sections, versioned prerequisites, every command paired with its real expected output, honest non-goals that are yours and not inherited from a brief.
  • Explain a system on one page — a component diagram and five paragraphs that let a competent engineer hold your architecture in their head, including the part that would surprise them.
  • Write operational documentation from evidence — a runbook whose failure catalogue comes from your own defect log, which names the irreversible commands, and which contains a rollback you have actually rehearsed on a timer.
  • Separate configuration from code and publish the contract that makes the separation usable, with no credential in the tree or the history.
  • Make an environment reproducible by one path — script or container — and prove it somewhere that is not your machine.
  • Version, tag, license, and publish a release a stranger can point at, with notes tied to your requirement and defect identifiers.
  • Assemble a handoff package that lets a competent stranger take custody without you, including the AI or vendor dependency you do not control.
  • Run an empirical acceptance test on your own work — recruit a tester, stay silent, log friction, fix, re-run.
  • Use an assistant as a drafter and yourself as the verifier, and report the correction rate without rounding it down.

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 3 and one who finds out in Week 7. 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 3 is a conversation and a scope cut. A red discovered in Week 7 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

Required deliverables

  1. README.md to the nine-section standard: what it is / who it is for / what it does not do with a status line; prerequisites with versions and check commands; install; configure; run with the action that proves it works; test; project layout; troubleshooting; license. Every command paired with its real expected output. Start from code/readme-template.md.
  2. docs/architecture.md §0 — a one-page overview added to the front of the file you started in Week 3: a component diagram (four to eight boxes, labeled arrows) and five paragraphs, the last naming the one thing that would surprise a new reader. Do not condense the Week-3 sections away to make room. They stay underneath §0 and get updated as built; a grader compares them to your code.
  3. docs/adr/README.md — an index of every decision record with number, decision, current status, and the consequence a reader would notice. Includes at least one record written this week for a decision that had never been recorded.
  4. 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 naming the variable. .env and credential files are gitignored. No credential in the working tree or the history — if one was ever committed, it is rotated, with the date, in docs/handoff.md. Say what you scanned with and what you found.
  5. One reproducible setup path. A script 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 and from README.md.
  6. docs/runbook.md — where it runs; deploy, from the tag; start/stop/restart with the health check and both healthy and unhealthy output; normal readings; at least four failure entries traced to real defects, one of which names a destructive command the operator must not run; rollback; escalation; a last-verified date and name with UNVERIFIED on anything you did not personally run.
  7. A rehearsed rollback. Numbered commands, executed once against a real deploy, wall-clock time recorded, and the migration question answered honestly: if a migration ran, does rolling back the code leave the schema ahead of it?
  8. 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. A packaged CLI or library satisfies this with a published installable artifact and install instructions somebody else verified. If your project cannot be publicly hosted — sensitive data, hardware dependency, institutional rule — say so in writing in docs/runbook.md §1, 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.
  9. 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 citing FR and DEF identifiers. If you shipped less than the specification promised, use an honest lower version and say why.
  10. 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 the third-party inventory table in docs/handoff.md §5 with every real obligation named.
  11. The handoff package. docs/handoff.md, built from code/handoff-template.md and filled completely: day-one path, week-one ramp ending in a merged change, accounts-and-costs ownership table, at least five landmines, the AI or volatile-vendor section, and the bus-factor register. No angle-bracket placeholders left.
  12. docs/clean-machine-test.md — the completed record from code/clean-machine-protocol.md: the acceptance action defined before either run, Run A (your reproduction on an environment that is not your machine, with the real transcript including failed attempts) and Run B (a real tester, on a clean environment, in silence), the friction log in the tester’s own words, the fixes applied with commits, and a second run after the fixes.
  13. Backlog groomed and logs current. Top five open issues with a clear title, the requirement or defect ID, acceptance criteria, and the files most likely involved; one labeled good-first-issue and referenced from the handoff guide. docs/hours-log.csv and docs/ai-usage.md current through this week.

What makes a clean-machine run valid

A run that breaks any of these is void and must be repeated. Each one exists because it is the rule students break.

  1. A genuinely clean environment — fresh container, fresh cloud development environment, borrowed laptop, or a new user account. Nothing your project installed is already there.
  2. For Run B, a real tester who is not you: competent, uncoached, has never run this project.
  3. Silence. You may watch and take notes. You may not speak, point, type, or fix.
  4. The repository URL is the only input. No verbal preamble, no messages, no “oh, you also need to…”.
  5. The clock runs from opening the repository to completing the acceptance action, defined before the run. Stop at sixty minutes and record the failure.
  6. Every stumble is logged, including the ones that look like the tester’s fault.

What “proof” looks like

Most students submit: “Tested the setup on a clean machine and it worked fine.” Nothing in that sentence can be checked. Which machine, when, 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
Attempt 1:   FAILED at step 3. `npm ci` errored — package-lock.json was gitignored
             since Week 2. Committed it (commit a91c4f2).
Attempt 2:   FAILED at step 5. Migrations ran; the 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, and the two defects it found are two afternoons your successor will never lose.

Normal-tier rubric (out of 100)

CriterionPoints
README.md complete to the nine-section standard, with honest status and non-goals that are yours12
Prerequisites pinned to real versions with check commands and named failure modes; every command paired with its real expected output6
docs/architecture.md §0 (diagram plus five paragraphs, surprise named, records linked; Week-3 sections retained and updated as built) and a current docs/adr/README.md index including the previously unrecorded decision9
Configuration contract complete and annotated; required values fail loudly; nothing secret in the tree or the history, anything exposed rotated with a date9
One reproducible setup path — fails fast, checks prerequisites, idempotent, ends with the next command; the abandoned alternative deleted8
docs/runbook.md: where it runs, deploy from the tag, health check, normal readings, four failure entries traced to real defects, destructive commands named, last-verified date9
Rollback written as numbered steps, rehearsed once against a real deploy, timed, migration question answered5
Deployed and reachable from the v1.0.0 tag, or the constraint argued in writing and the equivalent delivered7
Release v1.0.0: annotated tag pushed, readable release notes, CHANGELOG.md tied to FR and DEF identifiers6
LICENSE chosen and defended; third-party inventory with real obligations named4
docs/handoff.md: day-one path, week-one ramp, ownership table, five landmines, AI or vendor section, bus-factor register — no placeholders left10
docs/clean-machine-test.md: Run A transcript and Run B with a real tester, honestly recorded, friction in the tester’s own words12
Friction converted into documentation fixes, committed, and a second run recorded3
Total100

Read the twelve points for the clean-machine record carefully. They are awarded for real runs, honestly recorded — including ones that went badly. A run where the tester got stuck four times, you logged all four, fixed them, and re-ran scores higher than a suspiciously frictionless run with no friction log. A test you did not actually run scores zero, and it is easier to spot than students expect: real friction logs have the tester’s own words in them.


Medium Tier (+ up to 25% extra credit)

Pick what genuinely fits your project. Two done well beat five done thinly, and in a twenty-hour week two is the realistic number. Say in your submission which items you attempted; a grader who has to go hunting will find fewer than you built.

  • Documentation tested in CI. A job that, on a clean runner, executes the README’s install / configure / run / test sequence and fails when a documented command breaks. Wiring code/handoff_audit.py into the same job counts toward this. It is the only way documentation stops rotting.
  • Continuous delivery on tag. A workflow that, when a v* tag is pushed, builds, tests, and publishes the release. Ship the run URL.
  • A post-deploy smoke test that hits the deployed system — not localhost — and fails loudly, wired into the deploy step so a broken release cannot pass silently.
  • A demo that loads before the reader gives up. A 60–90 second recording or an animated GIF at the top of the README, committed to the repository rather than hotlinked. For a CLI, a real terminal session with real output.
  • A second clean-machine run on a different platform — different OS, different architecture, or browser-based versus local — with both records kept and the differences documented.
  • A standalone THIRD-PARTY-NOTICES.md, generated by your ecosystem’s license lister and regenerable with one command, rather than only the table in the handoff guide.
  • Secret scanning enabled on the repository, plus a written rotation procedure with dates and an owner for every credential.
  • A monitored deployment: a health endpoint, a log destination somebody other than you can read, and one alert that would actually reach a successor.

Anything you claim here must be demonstrated in the repository. A bootstrap script that exists but was never run by your tester earns nothing.


Hard Tier (+ up to 25% additional extra credit)

Required: the Succession Memo — two to three pages, in the repository as docs/succession-memo.md, 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 5 that is still load-bearing. Specific enough to be useful, honest enough to be uncomfortable.
  2. Price each gap. For every item, estimate what documenting it properly would cost in hours and what leaving it undocumented will cost your successor — then say which side of that trade you chose and why. “I chose not to spend four hours documenting the import pipeline’s edge cases because it will be rewritten before it is extended” is an engineering decision. “I ran out of time” is a report.
  3. The decision I would revisit. Name one record from Week 3 or Week 5 you now believe was wrong, or right for a reason that has stopped being true. Say what you would choose today, what changing it would cost, and whether you would actually spend that.
  4. An honest bus-factor residual. Not the register — what is still only in your head after this week. Everyone has something left. Naming it is worth more than pretending it is empty.
  5. 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, hedged where terms may change. Then the sentence students avoid: who pays this after I graduate, and what happens when nobody does?
  6. The deprecation plan. If nobody picks this up in six months: who archives the repository, what gets deleted, what happens to user data, and what the notice in README.md should say. Write the notice.

Graded on judgment, honesty, and self-awareness. A memo saying “everything is documented and it costs nothing to run” scores zero, because that is not true of any software system that has ever existed. A memo that says “I did not document why the sync job retries with a five-second backoff, because I never determined whether the upstream rate limit is per-key or per-IP; a successor will lose about a day finding out, and the way to find it is X” earns full marks. Specific, priced, honest, actionable — in that order.


Submission

Push everything, then post the repository URL, the documentation commit SHA, the v1.0.0 tag URL, and the deployed URL or your argued equivalent. The shape a grader will look for:

your-capstone/
├── README.md                     # nine sections, every command verified
├── LICENSE                       # SPDX id also stated in README.md
├── CHANGELOG.md                  # [1.0.0] Added / Changed / Fixed / Known issues
├── .env.example                  # the configuration contract
├── .gitignore                    # .env, credentials, local databases
├── script/setup                  # …OR Dockerfile + compose.yaml — ONE path, not both
├── docs/
│   ├── architecture.md           # EXTENDED — §0 overview above the Week-3 spec
│   ├── runbook.md                # NEW — where it runs, deploy, four failures, rollback
│   ├── handoff.md                # NEW — the handoff package
│   ├── clean-machine-test.md     # NEW — Run A, Run B, friction log, re-run
│   ├── ai-usage.md               # EXTENDED — successor-facing section + this week's rows
│   ├── succession-memo.md        # Hard tier only
│   ├── hours-log.csv             # current through Week 7
│   ├── requirements.md  test-plan.md  defect-log.md  test-results.md   # Weeks 2–6
│   └── adr/
│       ├── README.md             # NEW — the decision index
│       └── 0001-choose-the-stack.md  …
└── src/  tests/  .github/workflows/

Suggested commit message: docs: documentation set, v1.0.0 release, handoff package (milestone 7).


Hints

  • Start with the auditor, not the container. Run the Handoff Readiness Auditor on Monday before you touch anything, then work its remediation list top-down. Where your project is weakest is not the same for everyone.
  • Do the reps in order. The reps are sequenced so each feeds the next: diagnose, write, ship, prove.
  • Recruit your tester on Monday, not Thursday. The single most common way this milestone fails is discovering on Thursday night that nobody is available. Ask three people; one will say yes.
  • Write the non-goals first. The “what it does not do” paragraph is the hardest ten minutes in the README and the one that makes an experienced reader trust everything else.
  • Check what you inherited. If you adopted a Fast-Start brief, the brief’s non-goals, feature list, and suggested stack are not automatically yours. Read every sentence and ask whether you wrote it or inherited it.
  • 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 an outside connection. Start Tuesday, not Friday. If it eats six hours, switch to the argued-constraint fallback.
  • Rehearse the rollback while nothing is wrong. Twenty minutes on a calm Tuesday; impossible on a bad Friday.
  • Mine the defect log for the runbook. You already did the hard part in Week 6. Four real defects become four real failure entries in about forty minutes.
  • Write the landmines when you hit them. Every time you think “oh right, you have to do X first,” that is a landmine. Open the handoff guide and add it in the moment.
  • Use the assistant for gaps, not for facts. “You have never seen this project — list every question you still cannot answer” is the prompt that earns its keep. Then verify everything it hands you.
  • Run code/handoff_audit.py before every commit this week. It catches the variable you added on Wednesday and never documented.
  • Do not wait for the code to be finished. It will not be. Document what exists today and mark the rest honestly. A README describing ambitions is worth less than one describing the actual current state.

If something goes wrong

  • No tester available. Run A plus a strict solo Run B is the fallback — but say so plainly in the record and expect to lose part of the twelve points. Self-testing cannot find what you cannot un-know. Then recruit someone before Week 8.
  • The tester never reached the acceptance action. Record the failure at the checkpoint where it stopped, log the friction, fix, run again. A recorded failure followed by fixes and a successful second run is a full-credit outcome.
  • You broke the silence rule. Note it, void the run, start over — and treat every sentence you said out loud as a top-priority documentation fix.
  • You cannot deploy at all. Argue the constraint in writing and deliver the equivalent. That is graded as a constraint. Silence is not.

What Mastery Looks Like

A mastered submission 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 find a CHANGELOG.md with a Known-issues section naming two real defects the author chose not to fix, and said why. They find a rollback rehearsed on a date, with a time next to it. In the landmines section they find five things that could only have been written by the person who built it. And the clean-machine record is not clean: it shows a first run that went badly, in the tester’s own words, then fixes with commit SHAs, then a second run that took eleven minutes.

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/setup, and the guard added in ADR-0012.”

None of that is impressive writing. All of it is trustworthy writing, and at this level trustworthy is the higher bar. A grader reading a submission like that stops checking, because the author already did.

Coach’s Note — You will be tempted to run the clean-machine test with your most sympathetic friend, on a machine that already has half your stack installed, while narrating helpfully. That version will make you feel good on Thursday and cost you real points in Week 8, when a grader runs the honest version and it fails. Run the hard version now — the entire reason this milestone sits in Week 7 instead of Week 8 is that in Week 7 you still have a week.

When You’re Done

  • README.md scores 16+ out of 18 on the nine-section audit, and the auditor agrees
  • Every prerequisite pinned to a real version, with a check command and a named failure mode
  • Every command in every document executed by you, with real output pasted in
  • docs/architecture.md §0 written; every Week-3 section still present and updated as built
  • docs/adr/README.md complete, statuses current, the previously unrecorded decision written
  • .env.example is a complete annotated contract; required values have no defaults
  • No secret in the working tree or the history; anything ever exposed rotated, with the date
  • Exactly one setup path exists, works, and is the only one mentioned in README.md
  • docs/runbook.md: deploy from the tag, health check, normal readings, four real failure entries, destructive commands flagged, last-verified date
  • Rollback rehearsed once, numbered, timed, migration question answered
  • Deployed from the v1.0.0 tag and reachable, or the constraint argued and the equivalent delivered
  • Annotated tag pushed; release notes published; CHANGELOG.md cites FR and DEF identifiers
  • LICENSE in place with SPDX id in README.md; third-party obligations inventoried
  • docs/handoff.md filled with no placeholders: day one, week one, ownership, five landmines, AI or vendor section, bus-factor register
  • docs/clean-machine-test.md: Run A transcript, Run B with a real tester, friction log, fixes, second run
  • Top five issues groomed; one labeled good-first-issue and referenced from the handoff guide
  • python3 handoff_audit.py . reports zero errors
  • docs/hours-log.csv and docs/ai-usage.md current through Week 7; everything committed and pushed

A theological footnote. Habakkuk is told, “Write the vision; make it plain on tablets, so he may run who reads it” (Habakkuk 2:2, ESV) — and notice the purpose clause. Not so the vision is preserved. Not so the writer is credited. So that the one who reads it can run. Writing plainly is an act performed for somebody else’s speed: it costs the writer time in order to buy a stranger time. That is the whole economics of documentation, and it is also, in miniature, what Paul asks of Timothy — hand on what you received, prepared for hands that are not yours, to people who can hand it on again (2 Timothy 2:2). Eight weeks is a short time to grow attached to something, and you have anyway; this week you deliberately loosen your grip on it. That is not loss. Paul, writing about a different kind of building, states it as plain fact: “like a skilled master builder I laid a foundation, and someone else is building upon it” (1 Corinthians 3:10, ESV). Someone else is building on it. The only question left to you is how carefully you laid it for them. So this week you are not graded on eloquence. You are graded on whether someone else can run — and the clean-machine test is simply the moment you stop assuming they can and go find out. An honest failure this week is a gift; a comfortable illusion is a debt you will pay in Week 8.