Milestone 3

Technical Specification, Decision Records & Walking Skeleton

Apologetic question: "Why lay a foundation before you decorate?"

Milestone 3 — Technical Specification, Decision Records & Walking Skeleton

“According to the grace of God given to me, 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)

Chapter: Chapter 3 — Design, Decide, and Stand It Up Week: 3 of 8 · the last week of design, and the first week of code · you wear the architect, project manager, and release engineer hats Due: End of Week 3, committed and pushed. Monday’s design review opens these documents in front of you. Submit: The repository link at the commit tagged v0.1.0-skeleton, plus the URLs of one green CI run and one red one, in the Canvas dropbox. Where it lands in the final package: docs/architecture.md, three records in docs/adr/, docs/plan.md, docs/risk-register.md, docs/skeleton-trace.md, the script/ directory, .github/workflows/ci.yml, the ## Run it section of README.md, and the first real commits in src/. These feed the Week-8 rubric lines for design and architecture, working software, reproducibility, and engineering discipline — see Appendix D for the full grading contract. AI policy: Open, with two hard conditions. One: every version, price, limit, license, and compatibility claim that reaches your documents carries a vendor source and the date you checked it — an assistant may not be the source of a fact. Two: every generated line that reaches a commit is yours — your bug, your leaked key, your answer in the Week-8 defense. Log substantive use in docs/ai-usage.md: what you asked for, what you kept, what you rejected and why.


The Setup

Two weeks of documents are behind you, and one of them is a lie until this week.

Your requirements say what the system does. Your Week-1 brief suggested how to build it. Neither of those has ever been observed working. You believe the architecture holds; you have never once watched it hold. Between belief and observation there is a gap, and in an accelerated course the gap is where projects die — quietly, in Week 6, when the pieces are assembled for the first time and do not fit, with two weeks left and documentation not yet started.

So this week you close it, and you close it three ways at once.

You decide: you take the brief’s suggested stack, diff it against the project you actually scoped in Week 2, adopt what still fits, deviate where it does not, and write three one-page records that say why. You design: four to seven pages of specification — containers, responsibilities, contracts, a data model, and the one flow that crosses a boundary you do not control, with its failure branch written out. You plan: work packages against the 53 plannable hours you have left, and six risks with triggers a stranger could check. And then you stand it up: one real request, entering where a real user enters, travelling through every component you named, touching a real store, coming back as something a human can see.

It will render one row of text. It will not impress anybody. Then you hand it to a robot, which will clone your repository on every push for the rest of the term, follow your setup instructions, install from your lock file, lint, test, build, and run that one request through your system. That machine is your Week-8 grader, rehearsing, several hundred times, before the day it counts.

Nobody praises a foundation. Everybody who skipped one paid.


Learning Targets

You will demonstrate that you can:

  • Adapt an inherited architecture — check a suggested stack against your own requirements, and delete the parts your scope no longer justifies.
  • Defend a deviation in writing, naming what your project gains, what it loses, and what it costs in hours.
  • Design to a budget — produce a specification a stranger could build from, sized to eight weeks rather than sixteen.
  • Own a data model, with keys, invariants, stated nullability meanings, and a migration somebody else can run.
  • Specify failure, not just success: timeouts, retries, fallbacks, and what the user is told.
  • Plan against real capacity, with three-point estimates, a declared buffer, and a cut you made on purpose.
  • Manage risk with observable triggers and responses that are already tasks.
  • Build a vertical slice that exercises every architectural component end to end, with no unlabeled mocked hops.
  • Operate continuous integration as a working instrument — triggered automatically, capable of failing, and observed failing.
  • Use an assistant to accelerate scaffolding while remaining accountable for every committed line.

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

The bar. This is what “on pace at the end of Week 3” means, in about twenty hours.

Required deliverables

  1. docs/architecture.md — the technical specification, from Part 1 of code/design-pack-template.md: scope and boundary with the trust boundary drawn; context and container diagrams (source and rendered image under docs/diagrams/); a component responsibility table passing the single-owner and no-cycle audit; one interface contract per Must path, eight facts each; a data model with keys, types, nullability meanings, invariants, and a migration mechanism; one sequence flow with its failure table; eight edge cases tied to Must requirements; and an open-questions table with a blocker, an owner, and a date on every row.
  2. The brief diff — the adopt / deviate / delete table from Rep 1, as a section of the specification. If you brought your own project, run it against the template brief and your Week-1 assumptions.
  3. Three architecture decision records in docs/adr/, numbered from 0001, in the format of code/adr-one-page.md. Each dated, statused, attributed, tied to requirement identifiers, carrying the Adopt / Deviate field, at least two real options, negative consequences with budgeted hours, and a revisit trigger with a number or a date in it. One per deviation, minimum.
  4. docs/plan.md — the Weeks 4–8 capacity table, a declared 25% buffer, work packages decomposed into 1–6 hour tasks with requirement identifiers, three-point estimates and done-whens, a calibrated total, a verdict line against the plannable hours, and the scope-decision table recording what you cut.
  5. docs/risk-register.md — six risks, sorted by exposure, each with an observable trigger, an owner, and a response that already exists as a task in the plan.
  6. A walking skeleton that walks. One real request through every hop: real store, real table, at least one seeded row, real response, real rendered result. Any stubbed hop is labeled stub with the issue or ADR that says when it becomes real.
  7. A reproducible bootstrap. Runtime version pinned in a file, lock file committed, install performed from the lock file, configuration read from the environment, script/ holding one-word verbs, and a ## Run it section in README.md that names the prerequisite, gives the exact commands, and states what success looks like.
  8. Continuous integration on every push and every pull request into main, with the stages install → lint → test → build → smoke. Green on main.
  9. Evidence that CI can fail — one deliberately red run (URL), the log line that reported it, and the commit that turned it green.
  10. A smoke test committed as script/smoke, running in CI, that fails when the data store is unavailable.
  11. docs/skeleton-trace.md — the hop table, the requirement traceability rows, and the acceptance record: the date and commit where the skeleton first walked, the green run URL, the red run URL.
  12. Secrets hygiene and current logs. .gitignore present, .env.example committed with every variable the app reads, zero credentials anywhere in history, docs/hours-log.csv current through Week 3, docs/ai-usage.md carrying an entry for every generated artifact you kept.
  13. An annotated tagv0.1.0-skeleton, on the commit where the skeleton first walked.

Normal-tier rubric (out of 100)

CriterionPoints
The skeleton demonstrably walks end to end, with no unlabeled mocked hops20
Specification: containers, single-owner responsibility table, one interface contract per Must path16
Three one-page ADRs: adopt/deviate named, two real options, negative consequences, numeric revisit trigger12
CI runs automatically on push and pull request, green on main, with stages that can actually fail12
Data model: keys, types, stated nullability meanings, invariants, and a migration a stranger can run10
One sequence flow with its failure table; every external call has a timeout, a fallback, and a user-visible behavior8
docs/plan.md: tasks traced to requirements, three-point estimates, declared buffer, verdict against the hours left8
Red-build evidence: one deliberate failure, its log line, and the fix commit5
docs/risk-register.md: six risks with observable triggers, owners, and responses that are already tasks5
Reproducible bootstrap and a README.md “Run it” section that states what success looks like4
Total100

How the Big Line Is Actually Scored

Twenty points ride on “the skeleton demonstrably walks.” Students consistently misjudge that line, so here is exactly what the three grades look like on the same project.

20 / 20 — it walks.

$ git clone <the repo> /tmp/fresh && cd /tmp/fresh
$ cp .env.example .env && ./script/setup
  installed 214 packages from the lock file
  applied 2 migrations · seeded 1 item
$ ./script/start &
$ open http://127.0.0.1:8080/pantry
  -> "oat milk — expires in 3 days"
$ psql "$DATABASE_URL" -c "update items set name='rye bread'"
$ # reload the page -> "rye bread — expires in 3 days"

That last step is the proof. The page changed because the database changed. Nothing between them was faked.

13 / 20 — it stands. The route returns real data from a real store, but the rendered-result hop is a curl command in the README rather than anything a human sees, or one component in the middle is a pass-through that does nothing yet. Half the path is real, the claim is honest, the bones are not all connected.

5 / 20 — it is a drawing. The page is styled and impressive and the data is a hard-coded array, a fixture the tests inject, or a mock. Often accompanied by a very good-looking commit history. This is the most common Week-3 submission and it scores near the bottom, because the one thing the milestone exists to prove — that your architecture is real — has not been proved at all.

The difference between 20 and 5 is frequently two hours of work and one decision: whether you spent Wednesday on the data store or on the CSS.

If You Are Behind

Some of you arrive at Week 3 with requirements still unfinished. Triage in this order, and do not deviate:

  1. CI on every push, even with a trivial test. Ninety minutes. It starts paying immediately and never stops.
  2. The data-store hop. It is the hop most likely to break your architecture, so it is the one worth discovering first.
  3. The rest of the path, far end inward.
  4. The specification and the plan — which will be faster to write once the skeleton has told you what is true.
  5. Everything else.

What you must not do is spend this week perfecting Week 2’s document. In an eight-week course, a project that stops moving to polish a document presents slides in Week 8 instead of software.


Medium Tier (+ up to 25% extra credit)

Pick what fits your project. Depth here buys you hours in Weeks 6 and 7.

  • Deploy the skeleton now. A deploy stage that publishes the walking skeleton to a real URL on merge to main. It will render one row of text on the public internet, and Week 7’s hardest problem is already behind you. Verify the free-tier terms yourself before you point a pipeline at anything that bills.
  • A second slice — a write path. Create, then read back. Writes touch validation, transactions, and error handling, and they surface a different set of architectural lies than reads do.
  • Enforce the rule in the tool. Branch protection or a ruleset so main cannot take a merge without a green build. Its value is that it holds at 1 a.m. when your judgment does not.
  • A measured number in an ADR. Replace one guessed claim with something you obtained: the main-screen query timed at your NFR’s row count, a cold start on the candidate host, a p95 against the real API.
  • A superseding ADR. If building the skeleton overturned a decision you made on Tuesday, write 000N marking the earlier one Superseded by rather than editing it. Demonstrating the immutability discipline is worth more than getting it right the first time.
  • Automate the boring check. A CI step that fails the build if a tracked file matches a secrets pattern. Cheap, and it never gets tired.

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

The Design Memo — two to three pages, docs/decision-memo.md, addressed to whoever inherits this project in Week 8. No assistant can write this for you, because every sentence requires you to own a decision.

Cover all five:

  1. The place you deviated from the brief, argued against yourself. What is the strongest case that the brief was right and you were wrong? Why are you proceeding anyway? What would you have to see, and by when, to reverse it?
  2. What the skeleton proved, and what it disproved. Your specification made claims on Wednesday. Which did building the slice confirm, and which one did it break? If nothing broke, say so plainly and explain how you would know if you were wrong — a design that survives first contact perfectly is either excellent or untested.
  3. The re-estimate. You now have measured hours for real work. Take three tasks from docs/plan.md, compare estimate to actual, compute your correction factor, apply it to the rest of the plan, and state honestly whether Week 8 still fits in 53 plannable hours. If it does not, name what you will cut and say that you will decide it in Monday’s review.
  4. The hop you stubbed, and why. What it would have cost to make it real this week, what you did instead, and the specific week and issue where it becomes real. Argue the tradeoff; do not merely report it.
  5. The AI accounting. Which parts of this repository were generated? Quote one specific line or block you rejected, and explain what was wrong with it. That single example is what separates a student who reviewed the output from one who accepted it — and it is the question you will be asked in Week 8.

Graded on judgment and honesty. A memo that admits the plan no longer fits and names the cut scores higher than one that asserts everything is fine.


Submission

Tag the commit where the skeleton first walked, push the tag, and submit the link.

git tag -a v0.1.0-skeleton -m "The skeleton walks: one real request, end to end"
git push origin v0.1.0-skeleton

Your repository should look roughly like this by Friday. Names differ by stack; the shape should not.

your-capstone/
├── README.md               # with the "## Run it" section, and what success looks like
├── LICENSE
├── CHANGELOG.md
├── .gitignore              # first in history
├── .env.example            # every variable the app reads, placeholders only
├── <lock file>             # committed
├── <runtime version file>  # .nvmrc / .python-version / .tool-versions / go.mod
├── script/                 # setup, lint, test, build, start, smoke
├── src/                    # folders named after your specification's components
├── tests/
├── migrations/
├── docs/
│   ├── charter.md
│   ├── requirements.md
│   ├── architecture.md     # THIS WEEK
│   ├── plan.md             # THIS WEEK
│   ├── risk-register.md    # THIS WEEK
│   ├── skeleton-trace.md   # THIS WEEK
│   ├── hours-log.csv
│   ├── ai-usage.md
│   ├── decision-memo.md    # Hard tier only
│   ├── diagrams/
│   ├── adr/                # THIS WEEK — 0001, 0002, 0003
│   └── change-requests/    # a directory; it starts filling in Week 4
└── .github/workflows/ci.yml

In the Canvas dropbox: the repository link and commit hash, the green run URL, the red run URL, the recording from Rep 12, and — if you attempted Hard tier — the memo. Then take the weekly quiz. It is one of eight that together carry 15% of your grade, and it exists to tell you now whether you are on pace.


Hints

  • Start at the far end. Seed the row first, then make the service read it, then the route, then the page. Working outward-in leaves you with a beautiful front end waiting on a back end that does not exist. Far-end-in means every step you take is immediately observable.
  • Write the deviation ADR before you write the specification. Half the design decisions you are about to agonize over disappear the moment you delete a container your scope no longer justifies.
  • If you cannot get CI green in ninety minutes, shrink the pipeline. Checkout plus install, green, committed. Then lint. Then test. One stage per commit is faster than debugging five at once, every single time.
  • Do the two-command clone test on Wednesday, not Friday. It always finds something, and Wednesday-you has time to fix it.
  • Do not refactor while the skeleton is broken. Get one request through, ugly, and commit it. A tidy non-working system is worth nothing this week.
  • Write .env.example by grepping your own code for every environment variable it reads. You will find one you forgot, and that one is the one that breaks the grader.
  • Ask your assistant to review, not just to generate. “Here is my repository tree and my architecture document — where do they disagree?” is a far better use of it than “scaffold me a project.”
  • Do not put a secret in the repository. Not in a config file, not in an ADR, not “temporarily.” If one is already committed: rotate it first, then clean history, then log the incident. Appendix A covers the mechanics.

What Mastery Looks Like

A mastered Milestone 3 is small, unglamorous, and completely solid.

A stranger clones the repository, runs two commands, and within five minutes is looking at one row of real data that came out of a real store, through a real service, through a real route. They asked no questions, because the README named the prerequisite, the commands, and what success would look like. The src/ folders match the component names in docs/architecture.md, so the document reads as true rather than aspirational.

The specification is four to seven pages and every page decides something. There is a failure table under the risky flow, and it clearly changed an interface contract — you can see where. The ADRs say Adopt or Deviate in the header, and the deviation record names what the project loses without apologizing for it. The plan has a verdict line, and the verdict was over, and there is a scope-decision row with an identifier in it, dated this week.

And on every push, a machine somewhere ran the whole thing from scratch and said yes. There is one red run in the history, from Wednesday, made on purpose, with the fix commit right behind it — because the student wanted to know what failure looked like before failure chose the time.

Nothing about it demos well. Everything about it holds.

Coach’s Note — The single quiet temptation this week is to write yes in the “real?” column for a hop you faked. It takes four keystrokes, nobody in the world will catch you on Friday, and it will cost you the project. You do not plan around hops you hope work — you plan around hops you know work, and the whole point of docs/skeleton-trace.md is to keep those two lists separate in a week when you are tired and want them to be the same list. Write stub. It is the most professional word in the document.

When You’re Done

  • The brief diff is written, and every container your scope no longer justifies is deleted
  • Three ADRs, dated and numbered, each with Adopt/Deviate, negative consequences, and a numeric revisit trigger
  • docs/architecture.md: diagrams, single-owner responsibility table, one contract per Must path
  • Data model with keys, invariants, stated NULL meanings, and a migration script/setup applies
  • One sequence flow and its failure table; every external call has a timeout, a fallback, and a user-visible behavior
  • docs/plan.md has a verdict line against the plannable hours, and a scope-decision row if it was over
  • docs/risk-register.md: six risks, observable triggers, responses that are tasks
  • One real request travels every hop; no hop is faked without being labeled stub
  • script/setup takes a fresh clone to runnable in one command; runtime pinned; lock file committed
  • README.md has a ## Run it section that says what success looks like
  • CI runs on every push and every pull request into main, and main is green
  • You have watched your pipeline turn red on purpose and go green again
  • script/smoke passes in CI and fails with the data store stopped
  • docs/skeleton-trace.md complete: hops, traceability, acceptance record, honest stubs
  • .env.example committed; secrets audit run across the full history; zero credentials in it
  • docs/hours-log.csv and docs/ai-usage.md current; tagged v0.1.0-skeleton and pushed

A theological footnote. “According to the grace of God given to me, 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). Paul takes credit for the one part of the building nobody will ever admire, and then says the quiet thing this whole week depends on: someone else is building upon it. You are not building something you will keep. In five weeks you hand this repository to a stranger, and after that, in every job you hold, you will leave work behind for people you will never meet. The foundation is not for your comfort; it is for them, and that is what makes this an act of love and not merely of competence. Note also what the verse asks of you. Not speed — care. Care is a property of the builder, not of the building, and in a compressed course, where a machine can pour a plausible-looking foundation in ninety seconds and the deadline is always four days away, care is precisely the thing that has to come from you. Nothing here earns you anything before God; that was settled outside of you, by Christ, and it is not on any rubric. But the work still matters, because the neighbor is real. Take care how you build. Somebody else is going to.